diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index ca25f1637d5..00000000000 --- a/.eslintignore +++ /dev/null @@ -1,49 +0,0 @@ -# Javascript builds -node_modules -dist -__tests__ -tsc_out -.out -.changelog -.DS_Store -coverage -.cache -.tmp -**/Generated -**/build -css -packages/react-docs/.cache -packages/react-docs/static -packages/react-docs/public -packages/react-integration/results -packages/react-integration/demo-app-ts/public - -# package managers -yarn-error.log -lerna-debug.log - -# IDEs and editors -.idea -.project -.classpath -.c9 -*.launch -.settings -*.sublime-workspace -.history -.vscode - -# IDE - VSCode -.vscode -# For vim -*.swp - -# Deploy directory -docs - -# Copied types -DeprecatedPopperTypes.ts -DeprecatedTippyTypes.ts - -# Copied thirdparty -packages/react-core/src/helpers/Popper/thirdparty/**/* diff --git a/.eslintrc-md.json b/.eslintrc-md.json index 0f5929fbf83..9016f102667 100644 --- a/.eslintrc-md.json +++ b/.eslintrc-md.json @@ -1,6 +1,5 @@ { "plugins": [ - "markdown", "react", "patternfly-react" ], @@ -26,5 +25,6 @@ "react/jsx-uses-vars": "error", "react/no-unknown-property": 2, "react/jsx-no-undef": 2 - } -} \ No newline at end of file + }, + "extends": "plugin:markdown/recommended-legacy" +} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 1266039a489..00000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "env": { - "browser": true, - "node": true, - "es6": true - }, - "plugins": [ - "@typescript-eslint", - "react", - "react-hooks", - "prettier", - "patternfly-react" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react/recommended" - ], - "parserOptions": { - "sourceType": "module", - "ecmaFeatures": { - "jsx": true - } - }, - "settings": { - "react": { - "version": "16.4.0" - } - }, - "globals": { - "describe": "readonly", - "test": "readonly", - "jest": "readonly", - "expect": "readonly", - "require": "readonly", - "global": "writable", - "it": "readonly", - "afterEach": "readonly", - "beforeEach": "readonly" - }, - "rules": { - "@typescript-eslint/adjacent-overload-signatures": "error", - "@typescript-eslint/array-type": "error", - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/consistent-type-assertions": "error", - "@typescript-eslint/consistent-type-definitions": "error", - "@typescript-eslint/explicit-member-accessibility": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/indent": "off", - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-inferrable-types": "off", - "@typescript-eslint/no-misused-new": "error", - "@typescript-eslint/no-namespace": "error", - "@typescript-eslint/no-unused-vars": ["error", { - "argsIgnorePattern": "^_" - }], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/prefer-function-type": "error", - "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/unified-signatures": "error", - "@typescript-eslint/explicit-function-return-type": "off", - "arrow-body-style": "error", - "camelcase": ["error", { - "ignoreDestructuring": true - }], - "constructor-super": "error", - "curly": "error", - "dot-notation": "error", - "eqeqeq": [ - "error", - "smart" - ], - "guard-for-in": "error", - "max-classes-per-file": [ - "error", - 1 - ], - "max-len": "off", - "no-nested-ternary": "error", - "no-bitwise": "error", - "no-caller": "error", - "no-cond-assign": "error", - "no-console": "error", - "no-debugger": "error", - "no-empty": "error", - "no-eval": "error", - "no-new-wrappers": "error", - "no-prototype-builtins": "off", - "no-shadow": "off", - "no-throw-literal": "error", - "no-trailing-spaces": "off", - "no-undef-init": "error", - "no-unsafe-finally": "error", - "no-unused-expressions": ["error", { - "allowTernary": true, - "allowShortCircuit": true - }], - "no-unused-labels": "error", - "no-var": "error", - "object-shorthand": "error", - "one-var": [ - "error", - "never" - ], - "patternfly-react/import-tokens-icons": "error", - "patternfly-react/no-anonymous-functions": "error", - "prefer-const": "error", - "prettier/prettier": "error", - "radix": [ - "error", - "as-needed" - ], - "react/prop-types": 0, - "react/display-name": 0, - "react/no-unescaped-entities": ["error", {"forbid": [">", "}"]}], - "spaced-comment": "error", - "use-isnan": "error", - "patternfly-react/no-layout-effect": "error" - }, - "overrides": [ - { - "files": ["**/examples/*", "**/demos/examples/**/*"], - "rules": { - "patternfly-react/no-anonymous-functions": "off" - } - } - ] -} diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 5a29493d47f..00000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,8 +0,0 @@ -**Describe the issue. What is the expected and unexpected behavior?** - -**Please provide the steps to reproduce. Feel free to link CodeSandbox or another tool.** - - -**Is this a bug or enhancement? If this issue is a bug, is this issue blocking you or is there a work-around?** - -**What is your product and what release version are you targeting?** diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..f808ffbd94e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Help us to improve PatternFly +title: Bug - [Component] - [short description] +type: bug +assignees: '' + +--- + +**Describe the problem** +A clear and concise description of the problem. Which components are affected? + +**How do you reproduce the problem?** +Provide steps to reproduce. A [codesandbox](https://codesandbox.io/s/serverless-cherry-q9t3f ) demonstrating the problem is appreciated. + +**Expected behavior** +A clear and concise description of the expected behavior. + +**Is this issue blocking you?** +List the workaround if there is one. + +**Screenshots** +If applicable, add screenshots to help explain the issue. + +**What is your environment?** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**What is your product and what release date are you targeting?** + +**Any other information?** diff --git a/.github/ISSUE_TEMPLATE/devX_request.md b/.github/ISSUE_TEMPLATE/devX_request.md new file mode 100644 index 00000000000..10bfbe40624 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/devX_request.md @@ -0,0 +1,14 @@ +--- +name: Developer experience +about: Suggest an enhancement to the developer experience (DX). DX enhancements improve experience for those building UIs with PatternFly, but have little to no end user impact. +title: "[short description]" +type: DevX +assignees: '' + +--- +**Describe the enhancement or change** +A clear and concise description of the request. What is the expected outcome? + +**Is this request originating from a Red Hat product team? If so, which ones and is there any sort of deadline for this enhancement?** + +**Any other information?** diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000000..7e9c1bb19c3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,99 @@ +name: Feature request +description: Suggest a new feature or component for PatternFly. +title: "[Component] - [short description]" +labels: ["extension", "needs-triage"] +body: + - type: markdown + attributes: + value: | + ### Thanks for helping improve PatternFly! + Please fill out this form to help the team understand your proposal. + + - type: dropdown + id: category + attributes: + label: Is this a new component or an extension? + options: + - New Component + - Variant of an existing component + - Enhancement to a current feature + validations: + required: true + + - type: input + id: existing_component + attributes: + label: Existing Component + description: If this is a variant or enhancement, which component does it impact? + placeholder: e.g., Table, Select, Wizard + validations: + required: false + + - type: textarea + id: description + attributes: + label: Describe the feature + description: A clear and concise description of the new feature. + placeholder: What is the expected behavior? Is there any specific error handling? + validations: + required: true + + - type: textarea + id: user_story + attributes: + label: User Story + description: Providing context helps us understand the priority. + placeholder: As a [user role], I want to [action] so that [benefit]. + validations: + required: true + + - type: textarea + id: visuals + attributes: + label: Visuals & Mockups + description: Include links to Figma or upload screenshots for desktop/mobile views. + placeholder: | + - Figma link: + - Screenshots: (Drag images here) + validations: + required: false + + - type: textarea + id: interaction_states + attributes: + label: Interaction States & Variations + description: Describe the behavior across different states. + placeholder: | + - Initial/Empty: + - Loading: + - Error/Validation: + - Mobile/Responsive Viewport: + validations: + required: true + + - type: textarea + id: accessibility + attributes: + label: Accessibility (A11y) + description: Specific keyboard interaction or focus management requirements. + placeholder: e.g., Tab navigation, ARIA labels, or focus traps. + validations: + required: false + + - type: input + id: product_release + attributes: + label: Product & Target Release + description: If applicable, what is your product and target release date? + placeholder: e.g., OpenShift 4.15 + validations: + required: false + + - type: checkboxes + id: contribution_check + attributes: + label: Contribution + options: + - label: I am interested in contributing this feature. + - label: I have searched for similar existing requests. + required: true diff --git a/.github/ISSUE_TEMPLATE/tech_debt_request.md b/.github/ISSUE_TEMPLATE/tech_debt_request.md new file mode 100644 index 00000000000..fe899df86a0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/tech_debt_request.md @@ -0,0 +1,14 @@ +--- +name: Tech debt +about: Improvements to code that do not affect either user or product developers’ experiences. +title: "[short description]" +type: 'Tech debt' +assignees: '' + +--- +**Describe the enhancement or change** +A clear and concise description of the request. What is the expected outcome? + +**Is this request originating from a Red Hat product team? If so, which ones and is there any sort of deadline for this enhancement?** + +**Any other information?** diff --git a/.github/actions/setup-project/action.yml b/.github/actions/setup-project/action.yml new file mode 100644 index 00000000000..07aaccbecde --- /dev/null +++ b/.github/actions/setup-project/action.yml @@ -0,0 +1,54 @@ +name: Set up and build project +inputs: + skip-build: + description: Skip the build step + required: false + default: 'false' + skip-build-cache: + description: Skip the build cache step + required: false + default: 'false' +runs: + using: composite + steps: + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + check-latest: true + + - name: Enable Corepack + shell: bash + run: corepack enable + + - name: Get Yarn configuration + id: yarn-config + shell: bash + run: | + echo "cache-folder=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT + + # TODO: This can be simplified to use the `cache` option of the `actions/setup-node` action when it supports Corepack. + # See: https://github.com/actions/setup-node/issues/531 + - uses: actions/cache@v4 + name: Setup Yarn cache + with: + # Also cache Cypress binary. + path: | + ~/.cache/Cypress + ${{ steps.yarn-config.outputs.cache-folder }} + key: ${{ runner.os }}-yarn-cache-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn-cache- + + - name: Install dependencies + shell: bash + run: yarn install --immutable + + - name: Run build + if: inputs.skip-build != 'true' + shell: bash + run: yarn build && yarn build:umd + env: + # Disable V8 compile cache to hard crashes in Node.js. This can likely be removed once upgraded to the next LTS version (version 22). + # See: https://github.com/nodejs/node/issues/51555 + DISABLE_V8_COMPILE_CACHE: 1 diff --git a/.github/generate-workflows.js b/.github/generate-workflows.js deleted file mode 100644 index b4a9f17307b..00000000000 --- a/.github/generate-workflows.js +++ /dev/null @@ -1,53 +0,0 @@ -/* For some reason Github's composite actions are limited to a small set - * of actions AND even if you get them working, the composite actions don't - * list all the steps out in an easily debuggable way. - * - * I've written this so common parts of pr preview/release builds need not - * be repeated. - */ -const path = require('path'); -const fs = require('fs'); - -const inDir = path.join(__dirname, 'workflows-src'); -const outDir = path.join(__dirname, 'workflows'); -const partialsDir = path.join(inDir, 'partials'); -const yamlRegex = /\.ya?ml$/; - -const partials = fs.readdirSync(partialsDir).reduce((acc, f) => { - acc[f.replace(yamlRegex, '')] = fs.readFileSync(path.join(partialsDir, f), 'utf8').trim(); - return acc; -}, {}); - -function templateReplace(contents) { - Object.entries(partials).forEach(([key, val]) => { - const regexText = `([ \\t]*)%${key}%`; - const match = contents.match(new RegExp(regexText)); - if (match) { - const spacing = match[1]; - val = `${spacing}${val.replace(/\n/g, '\n' + spacing)}`; - contents = contents.replace(new RegExp(regexText, 'g'), val); - } - }); - - return contents; -} - -// Partials can have other partials -Object.entries(partials).forEach(([key, val]) => { - partials[key] = templateReplace(val); -}); - -if (!fs.existsSync(outDir)) { - fs.mkdirSync(outDir); -} - -fs.readdirSync(inDir) - .filter(f => f.match(yamlRegex)) - .forEach(f => { - let contents = fs.readFileSync(path.join(inDir, f), 'utf8'); - - contents = templateReplace(contents); - contents = `### WARNING -- this file was generated by ${process.argv[1].split(path.sep).pop()}\n${contents}`; - fs.writeFileSync(path.join(outDir, f), contents); - }); - diff --git a/.github/promote.sh b/.github/promote.sh new file mode 100755 index 00000000000..d8700acd96e --- /dev/null +++ b/.github/promote.sh @@ -0,0 +1,30 @@ +#!/bin/bash +GIT_USERNAME="patternfly-build" +GH_REPO=${GITHUB_REPOSITORY} +REPO="github.com/${GH_REPO}" +echo "Preparing release environment..." +git config user.email "patternfly-build@redhat.com" +git config user.name ${GIT_USERNAME} +echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc + +# Lerna is complicated. Commands: https://github.com/lerna/lerna/tree/master/commands +# Identify packages that have been updated since the previous tagged release +# Update their versions and changelogs according to angular commit guidelines +# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit + +#if [[ ! -z "${PATTERNFLY_VERSION}" ]]; then +# echo "Updating to @patternfly/patternfly: ${PATTERNFLY_VERSION}" +# npm pkg set dependencies.@patternfly/patternfly=${PATTERNFLY_VERSION} --workspace @patternfly/react-docs +# npm pkg set devDependencies.@patternfly/patternfly=${PATTERNFLY_VERSION} --workspace @patternfly/react-core --workspace @patternfly/react-styles --workspace @patternfly/react-tokens --workspace @patternfly/react-icons +#fi + +# publish to npm +# yarn run lerna publish --conventional-commits --conventional-graduate --no-private --dist-tag=latest --yes + +# immediately after promote - set up repo for next prerelease +yarn run lerna version preminor --force-publish --conventional-commits --no-private --yes --preid prerelease + +# dry run +# yarn run lerna version --conventional-commits --conventional-graduate --no-private --yes --no-git-tag-version --no-push + + diff --git a/.github/release.sh b/.github/release.sh index 374b2f3e514..506097c32a9 100755 --- a/.github/release.sh +++ b/.github/release.sh @@ -17,7 +17,10 @@ echo "Doing a release..." LOG=$(git log --format="%s" -1 | grep -Poe "#\d+") PR_NUM=${LOG:1} -yarn run lerna publish --conventional-commits --create-release=github --no-verify-access --yes 2>&1 | tee lerna-output.txt +yarn run lerna publish prerelease --preid=prerelease --dist-tag=prerelease --yes 2>&1 | tee lerna-output.txt + +# use lerna command below for dry run +#yarn run lerna version prerelease --preid=prerelease --yes --no-git-tag-version --no-push | tee lerna-output.txt if grep -i "Successfully published" lerna-output.txt; # Leave a Github comment then diff --git a/.github/renovate.json b/.github/renovate.json index 63158b99095..663f5774573 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,31 +1,15 @@ { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base" + "config:recommended" ], - "enabledManagers": ["npm"], + "rangeStrategy": "bump", "packageRules": [ { - "packagePatterns": ["*"], - "excludePackagePatterns": [ - "@patternfly/patternfly", - "@patternfly/patternfly-a11y", - "theme-patternfly-org" + "matchUpdateTypes": [ + "major" ], "enabled": false - }, - { - "datasources": ["npm"], - "packageNames": [ - "@patternfly/patternfly-a11y", - "theme-patternfly-org" - ] - }, - { - "datasources": ["npm"], - "packageNames": [ - "@patternfly/patternfly" - ], - "followTag": "prerelease" } ] } diff --git a/.github/split.js b/.github/split.js deleted file mode 100644 index 11a6610de7c..00000000000 --- a/.github/split.js +++ /dev/null @@ -1,14 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const BASE_DIR = path.join(__dirname, '../packages/react-integration/cypress/integration'); -const WORKER_NUM = +process.env['WORKER_NUM']; -const WORKER_COUNT = +process.env['WORKER_COUNT']; - -const testFiles = fs.readdirSync(BASE_DIR) - .sort() - .filter((_, i) => i % WORKER_COUNT === WORKER_NUM) - .map(f => path.join(BASE_DIR, f)); - -console.log(testFiles.join(' ')); - diff --git a/.github/split.mjs b/.github/split.mjs new file mode 100644 index 00000000000..46e12072955 --- /dev/null +++ b/.github/split.mjs @@ -0,0 +1,15 @@ +/* eslint-disable no-console */ +import fs from 'node:fs'; +import path from 'node:path'; + +const BASE_DIR = path.resolve(import.meta.dirname, '../packages/react-integration/cypress/integration'); +const WORKER_NUM = +process.env.WORKER_NUM; +const WORKER_COUNT = +process.env.WORKER_COUNT; + +const testFiles = fs + .readdirSync(BASE_DIR) + .sort() + .filter((_, i) => i % WORKER_COUNT === WORKER_NUM) + .map((f) => path.join(BASE_DIR, f)); + +console.log(testFiles.join(' ')); diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index f4e6ae06a53..00000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Configuration for probot-stale - https://github.com/probot/stale -# Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 60 - -# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. -# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 14 - -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security - - accessibility - - "breaking change :boom:" - -# Label to use when marking as stale -staleLabel: wontfix - -# Comment to post when marking as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. - -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false - -# Limit the number of actions per hour, from 1-30. Default is 30 -limitPerRun: 30 diff --git a/.github/upload-preview.js b/.github/upload-preview.js deleted file mode 100644 index 5fc94f2a2eb..00000000000 --- a/.github/upload-preview.js +++ /dev/null @@ -1,92 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { Octokit } = require('@octokit/rest'); -const octokit = new Octokit({ auth: process.env.GH_PR_TOKEN }); -const surge = require('surge'); -const publishFn = surge().publish(); - -// From github actions -const ghrepo = process.env.GITHUB_REPOSITORY || ''; - -const owner = process.env.CIRCLE_PROJECT_USERNAME || ghrepo.split('/')[0]; // patternfly -const repo = process.env.CIRCLE_PROJECT_REPONAME || ghrepo.split('/')[1]; -const prnum = process.env.CIRCLE_PR_NUMBER || process.env.GH_PR_NUM; -const prbranch = process.env.CIRCLE_BRANCH || process.env.GITHUB_REF.split('/').pop(); - -const uploadFolder = process.argv[2]; -if (!uploadFolder) { - console.log('Usage: upload-preview uploadFolder'); - process.exit(1); -} - -const uploadFolderName = path.basename(uploadFolder); -let uploadURL = `${repo}-${prnum ? `pr-${prnum}` : prbranch}`.replace(/[\/|\.]/g, '-'); - -switch(uploadFolderName) { - case 'coverage': - uploadURL += '-a11y.surge.sh'; - break; - case 'public': - uploadURL += '.surge.sh'; - break; - default: - uploadURL += `-${uploadFolderName}`; - uploadURL += '.surge.sh'; - break; -} - -publishFn({ - project: uploadFolder, - p: uploadFolder, - domain: uploadURL, - d: uploadURL, - e: 'https://surge.surge.sh', - endpoint: 'https://surge.surge.sh' -}); - -function tryAddComment(comment, commentBody) { - if (!commentBody.includes(comment)) { - return comment; - } - return ''; -} - -if (prnum) { - octokit.issues.listComments({ - owner, - repo, - issue_number: prnum - }) - .then(res => res.data) - .then(comments => { - let commentBody = ''; - const existingComment = comments.find(comment => comment.user.login === 'patternfly-build'); - if (existingComment) { - commentBody += existingComment.body.trim(); - commentBody += '\n\n'; - } - - if (uploadFolderName === 'public') { - commentBody += tryAddComment(`Preview: https://${uploadURL}`, commentBody); - } - else if (uploadFolderName === 'dist') { - commentBody += tryAddComment(`A11y report: https://${uploadURL}`, commentBody); - } - - if (existingComment) { - octokit.issues.updateComment({ - owner, - repo, - comment_id: existingComment.id, - body: commentBody - }).then(() => console.log('Updated comment!')); - } else { - octokit.issues.createComment({ - owner, - repo, - issue_number: prnum, - body: commentBody - }).then(() => console.log('Created comment!')); - } - }); -} diff --git a/.github/upload-preview.mjs b/.github/upload-preview.mjs new file mode 100644 index 00000000000..704f2347538 --- /dev/null +++ b/.github/upload-preview.mjs @@ -0,0 +1,98 @@ +/* eslint-disable no-console, camelcase */ +import { Octokit } from '@octokit/rest'; +import path from 'node:path'; +import surge from 'surge'; + +const octokit = new Octokit({ auth: process.env.GH_PR_TOKEN }); +const publishFn = surge().publish(); + +// From github actions +const ghrepo = process.env.GITHUB_REPOSITORY || ''; +const [owner, repo] = ghrepo.split('/'); +const prnum = process.env.GH_PR_NUM; +const prbranch = process.env.GITHUB_REF.split('/').pop(); + +const uploadFolder = process.argv[2]; +if (!uploadFolder) { + process.exit(1); +} + +const uploadFolderName = path.basename(uploadFolder); +let uploadURL = `pf-react-${prnum ? `pr-${prnum}` : prbranch}`.replace(/[/|.]/g, '-'); + +switch (uploadFolderName) { + case 'coverage': + uploadURL += '-a11y.surge.sh'; + break; + case 'public': + if (!prnum && prbranch === 'main') { + uploadURL = 'pf-react-staging.patternfly.org'; + } else { + uploadURL += '.surge.sh'; + } + break; + default: + uploadURL += `-${uploadFolderName}`; + uploadURL += '.surge.sh'; + break; +} + +publishFn({ + project: uploadFolder, + p: uploadFolder, + domain: uploadURL, + d: uploadURL, + e: 'https://surge.surge.sh', + endpoint: 'https://surge.surge.sh' +}); + +function tryAddComment(comment, commentBody) { + if (!commentBody.includes(comment)) { + return comment; + } + return ''; +} + +if (prnum) { + octokit.issues + .listComments({ + owner, + repo, + issue_number: prnum + }) + .then((res) => res.data) + .then((comments) => { + let commentBody = ''; + const existingComment = comments.find((comment) => comment.user.login === 'patternfly-build'); + if (existingComment) { + commentBody += existingComment.body.trim(); + commentBody += '\n\n'; + } + + if (uploadFolderName === 'public') { + commentBody += tryAddComment(`Preview: https://${uploadURL}`, commentBody); + } else if (uploadFolderName === 'coverage') { + commentBody += tryAddComment(`A11y report: https://${uploadURL}`, commentBody); + } + + if (existingComment) { + octokit.issues + .updateComment({ + owner, + repo, + comment_id: existingComment.id, + body: commentBody + }) + .then(() => console.log('Updated comment!')); + } else { + octokit.issues + .createComment({ + owner, + repo, + issue_number: prnum, + body: commentBody + }) + .then(() => console.log('Created comment!')); + } + }); +} diff --git a/.github/workflows-src/partials/build.yml b/.github/workflows-src/partials/build.yml deleted file mode 100644 index 3c3672e2b66..00000000000 --- a/.github/workflows-src/partials/build.yml +++ /dev/null @@ -1,8 +0,0 @@ -build: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - steps: - %checkout% - %install% - %dist% diff --git a/.github/workflows-src/partials/checkout.yml b/.github/workflows-src/partials/checkout.yml deleted file mode 100644 index 1cf27edd29d..00000000000 --- a/.github/workflows-src/partials/checkout.yml +++ /dev/null @@ -1,8 +0,0 @@ -- uses: actions/checkout@v2 -# Yes, we really want to checkout the PR -- run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi diff --git a/.github/workflows-src/partials/demo_app.yml b/.github/workflows-src/partials/demo_app.yml deleted file mode 100644 index ae66f8650e5..00000000000 --- a/.github/workflows-src/partials/demo_app.yml +++ /dev/null @@ -1,16 +0,0 @@ -demo_app: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - %checkout% - %install% - %dist% - - name: Build demo app - run: yarn build:integration - - name: Upload demo app - uses: actions/upload-artifact@v2 - with: - name: demo-app - path: packages/react-integration/demo-app-ts/public diff --git a/.github/workflows-src/partials/dist.yml b/.github/workflows-src/partials/dist.yml deleted file mode 100644 index 22e187f23f0..00000000000 --- a/.github/workflows-src/partials/dist.yml +++ /dev/null @@ -1,11 +0,0 @@ -- uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} -- name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' diff --git a/.github/workflows-src/partials/docs.yml b/.github/workflows-src/partials/docs.yml deleted file mode 100644 index 4d5d49717bf..00000000000 --- a/.github/workflows-src/partials/docs.yml +++ /dev/null @@ -1,28 +0,0 @@ -docs: - runs-on: ubuntu-latest - needs: build - env: - SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }} - SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} - GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }} - GH_PR_NUM: ${{ github.event.number }} - steps: - %checkout% - %install% - %dist% - - uses: actions/cache@v2 - id: docs-cache - name: Cache webpack - with: - path: '.cache' - key: ${{ runner.os }}-v4-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - name: Build docs - run: yarn build:docs - - name: Upload docs - run: node .github/upload-preview.js packages/react-docs/public - if: always() -# - name: a11y tests -# run: yarn serve:docs & yarn test:a11y -# - name: Upload a11y results -# run: node .github/upload-preview.js packages/react-docs/coverage -# if: always() diff --git a/.github/workflows-src/partials/install.yml b/.github/workflows-src/partials/install.yml deleted file mode 100644 index 289194abc7d..00000000000 --- a/.github/workflows-src/partials/install.yml +++ /dev/null @@ -1,15 +0,0 @@ -- uses: actions/setup-node@v1 - with: - node-version: '14' -- uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} -- run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - diff --git a/.github/workflows-src/partials/lint.yml b/.github/workflows-src/partials/lint.yml deleted file mode 100644 index 2cb58094e09..00000000000 --- a/.github/workflows-src/partials/lint.yml +++ /dev/null @@ -1,21 +0,0 @@ -lint: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - %checkout% - %install% - - uses: actions/cache@v2 - id: lint-cache - name: Load lint cache - with: - path: '.eslintcache' - key: ${{ runner.os }}-lint-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - name: ESLint - run: yarn lint:ts - - name: MDLint - run: yarn lint:md - - name: '@patternfly/patternfly versions match' - run: yarn lint:versions - diff --git a/.github/workflows-src/partials/test_integration.yml b/.github/workflows-src/partials/test_integration.yml deleted file mode 100644 index 292bd347657..00000000000 --- a/.github/workflows-src/partials/test_integration.yml +++ /dev/null @@ -1,25 +0,0 @@ -test_integration: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: demo_app - strategy: - fail-fast: false - matrix: - worker_num: [0, 1, 2, 3, 4] - worker_count: [5] - steps: - %checkout% - %install% - %dist% - - name: Download demo app - uses: actions/download-artifact@v2 - with: - name: demo-app - path: packages/react-integration/demo-app-ts/public - - run: printenv - - name: Cypress tests - run: yarn serve:integration & yarn test:integration -s $(node .github/split.js) - env: - WORKER_NUM: ${{ matrix.worker_num }} - WORKER_COUNT: ${{ matrix.worker_count }} diff --git a/.github/workflows-src/partials/test_jest.yml b/.github/workflows-src/partials/test_jest.yml deleted file mode 100644 index a04be2eedff..00000000000 --- a/.github/workflows-src/partials/test_jest.yml +++ /dev/null @@ -1,11 +0,0 @@ -test_jest: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - %checkout% - %install% - %dist% - - name: PF4 Jest Tests - run: yarn test --maxWorkers=2 diff --git a/.github/workflows-src/pr-preview.yml b/.github/workflows-src/pr-preview.yml deleted file mode 100644 index cc28536e0e2..00000000000 --- a/.github/workflows-src/pr-preview.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: build-test-deploy -on: pull_request_target -jobs: - %build% - %lint% - %test_jest% - %docs% - %demo_app% - %test_integration% - diff --git a/.github/workflows-src/release.yml b/.github/workflows-src/release.yml deleted file mode 100644 index 3733ec2cd0c..00000000000 --- a/.github/workflows-src/release.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: release -on: - push: - branches: - - main -jobs: - %build% - %lint% - %test_jest% - %docs% - %demo_app% - %test_integration% - deploy: - runs-on: ubuntu-latest - needs: [lint, test_jest, docs, test_integration] - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - GH_TOKEN: ${{ secrets.GH_TOKEN_REDALLEN }} # needs to be an admin token to get around branch protection - GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }} - steps: - - uses: actions/checkout@v2 - with: - token: ${{ secrets.GH_TOKEN_REDALLEN }} # needs to be an admin token to get around branch protection - %install% - %dist% - - name: Deploy to NPM and Github - run: .github/release.sh - diff --git a/.github/workflows/add-new-issues-to-project.yml b/.github/workflows/add-new-issues-to-project.yml new file mode 100644 index 00000000000..ec999f05b1a --- /dev/null +++ b/.github/workflows/add-new-issues-to-project.yml @@ -0,0 +1,40 @@ +name: Add new issues to PatternFly Issues project +on: + issues: + types: + - opened +jobs: + add-to-project: + name: Add issue to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v1.0.2 + with: + project-url: https://github.com/orgs/patternfly/projects/7 + github-token: ${{ secrets.GH_PROJECTS }} + label-issue: + runs-on: ubuntu-latest + steps: + - name: Team Membership Checker + id: teamcheck + # You may pin to the exact commit or the version. + # uses: TheModdingInquisition/actions-team-membership@a69636a92bc927f32c3910baac06bacc949c984c + uses: TheModdingInquisition/actions-team-membership@v1.0 + with: + # Repository token. GitHub Action token is used by default(recommended). But you can also use the other token(e.g. personal access token). + token: ${{ secrets.GH_READ_ORG_TOKEN }} + # The team to check for. + team: 'frequent-flyers' + # The organization of the team to check for. Defaults to the context organization. + organization: 'patternfly' + # If the action should exit if the user is not part of the team. + exit: false + + - name: Add label if user is a team member + if: steps.teamcheck.outputs.permitted == 'true' + run: | + curl -X POST \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/labels \ + -d '{"labels":["PF Team"]}' diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 00000000000..ba9dbe11555 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,49 @@ +name: Documentation +on: + pull_request_target: + workflow_call: + secrets: + SURGE_LOGIN: + required: true + SURGE_TOKEN: + required: true + GH_PR_TOKEN: + required: true +jobs: + deploy: + name: Build, test & deploy + runs-on: ubuntu-latest + env: + SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }} + SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} + GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }} + GH_PR_NUM: ${{ github.event.number }} + steps: + - name: Check out project from PR branch + if: github.event_name == 'pull_request_target' + uses: actions/checkout@v4 + with: + # Checkout the merge commit so that we can access the PR's changes. + # This is nessesary because `pull_request_target` checks out the base branch (e.g. `main`) by default. + ref: refs/pull/${{ env.GH_PR_NUM }}/head + + - name: Check out project + if: github.event_name != 'pull_request_target' + uses: actions/checkout@v4 + + - name: Set up and build project + uses: ./.github/actions/setup-project + + - name: Build documentation + run: yarn build:docs + + - name: Upload documentation + if: always() + run: node .github/upload-preview.mjs packages/react-docs/public + + - name: Run accessibility tests + run: yarn serve:docs & yarn test:a11y + + - name: Upload accessibility results + if: always() + run: node .github/upload-preview.mjs packages/react-docs/coverage diff --git a/.github/workflows/extensions.yml b/.github/workflows/extensions.yml new file mode 100644 index 00000000000..3f5632da74f --- /dev/null +++ b/.github/workflows/extensions.yml @@ -0,0 +1,15 @@ +name: Add relevant issues to extensions project board +on: + issues: + types: + - labeled +jobs: + add-to-extensions: + if: github.event.label.name == 'extension' + name: Add issue to extensions board + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v1.0.2 + with: + project-url: https://github.com/orgs/patternfly/projects/12 + github-token: ${{ secrets.GH_PROJECTS }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000000..f0e9552023e --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,99 @@ +name: CI +on: + pull_request: + workflow_call: +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Check out project + uses: actions/checkout@v4 + + - name: Set up project + uses: ./.github/actions/setup-project + with: + skip-build: true + + - uses: actions/cache@v4 + name: Cache files proccesed by ESLint + with: + path: .eslintcache + key: ${{ runner.os }}-eslint-cache + + - name: Run linter + run: yarn lint:all + + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Check out project + uses: actions/checkout@v4 + + - name: Set up and build project + uses: ./.github/actions/setup-project + + unit-tests: + name: Unit tests + runs-on: ubuntu-latest + needs: build + steps: + - name: Check out project + uses: actions/checkout@v4 + + - name: Set up and build project + uses: ./.github/actions/setup-project + + - name: Run tests + run: yarn test --maxWorkers=2 + + demo-app: + name: Build demo app + runs-on: ubuntu-latest + needs: build + steps: + - name: Check out project + uses: actions/checkout@v4 + + - name: Set up and build project + uses: ./.github/actions/setup-project + + - name: Build demo app + run: yarn build:integration + + - name: Upload demo app + uses: actions/upload-artifact@v4 + with: + name: demo-app + path: packages/react-integration/demo-app-ts/dist + + integration-tests: + name: Integration tests + runs-on: ubuntu-latest + needs: demo-app + strategy: + fail-fast: false + matrix: + worker: [0, 1, 2, 3, 4] + steps: + - name: Check out project + uses: actions/checkout@v4 + + - name: Set up and build project + uses: ./.github/actions/setup-project + + - name: Download demo app + uses: actions/download-artifact@v4 + with: + name: demo-app + path: packages/react-integration/demo-app-ts/dist + + - name: Print environment variables + run: printenv + + - name: Run Cypress tests + run: yarn serve:integration & yarn test:integration -s $(node .github/split.mjs) + env: + WORKER_NUM: ${{ matrix.worker }} + WORKER_COUNT: 5 diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml deleted file mode 100644 index 257b795deea..00000000000 --- a/.github/workflows/pr-preview.yml +++ /dev/null @@ -1,283 +0,0 @@ -### WARNING -- this file was generated by generate-workflows.js -name: build-test-deploy -on: pull_request_target -jobs: - build: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - lint: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: lint-cache - name: Load lint cache - with: - path: '.eslintcache' - key: ${{ runner.os }}-lint-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - name: ESLint - run: yarn lint:ts - - name: MDLint - run: yarn lint:md - - name: '@patternfly/patternfly versions match' - run: yarn lint:versions - test_jest: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - name: PF4 Jest Tests - run: yarn test --maxWorkers=2 - docs: - runs-on: ubuntu-latest - needs: build - env: - SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }} - SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} - GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }} - GH_PR_NUM: ${{ github.event.number }} - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: docs-cache - name: Cache webpack - with: - path: '.cache' - key: ${{ runner.os }}-v4-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - name: Build docs - run: yarn build:docs - - name: Upload docs - run: node .github/upload-preview.js packages/react-docs/public - if: always() - # - name: a11y tests - # run: yarn serve:docs & yarn test:a11y - # - name: Upload a11y results - # run: node .github/upload-preview.js packages/react-docs/coverage - # if: always() - demo_app: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - name: Build demo app - run: yarn build:integration - - name: Upload demo app - uses: actions/upload-artifact@v2 - with: - name: demo-app - path: packages/react-integration/demo-app-ts/public - test_integration: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: demo_app - strategy: - fail-fast: false - matrix: - worker_num: [0, 1, 2, 3, 4] - worker_count: [5] - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - name: Download demo app - uses: actions/download-artifact@v2 - with: - name: demo-app - path: packages/react-integration/demo-app-ts/public - - run: printenv - - name: Cypress tests - run: yarn serve:integration & yarn test:integration -s $(node .github/split.js) - env: - WORKER_NUM: ${{ matrix.worker_num }} - WORKER_COUNT: ${{ matrix.worker_count }} - diff --git a/.github/workflows/promote.yml b/.github/workflows/promote.yml new file mode 100644 index 00000000000..7d85ee4d25f --- /dev/null +++ b/.github/workflows/promote.yml @@ -0,0 +1,27 @@ +name: Promote +on: + workflow_dispatch: + inputs: + patternfly-version: + description: The version of PatternFly (`@patternfly/patternfly`) to promote to. + required: false +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Check out project + uses: actions/checkout@v4 + with: + # Pass in an administrator token to get around branch protection. + token: ${{ secrets.GH_TOKEN_REDALLEN }} + + - name: Set up and build project + uses: ./.github/actions/setup-project + with: + skip-build-cache: true + + - name: Deploy to NPM and Github + run: .github/promote.sh + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + PATTERNFLY_VERSION: ${{ github.event.inputs.patternfly-version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 088edbcf98f..66e9c84d2df 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,324 +1,42 @@ -### WARNING -- this file was generated by generate-workflows.js -name: release +name: Release on: push: branches: - main +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - build: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - lint: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: lint-cache - name: Load lint cache - with: - path: '.eslintcache' - key: ${{ runner.os }}-lint-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - name: ESLint - run: yarn lint:ts - - name: MDLint - run: yarn lint:md - - name: '@patternfly/patternfly versions match' - run: yarn lint:versions - test_jest: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - name: PF4 Jest Tests - run: yarn test --maxWorkers=2 + ci: + name: CI + uses: ./.github/workflows/main.yml + docs: - runs-on: ubuntu-latest - needs: build - env: - SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }} - SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} - GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }} - GH_PR_NUM: ${{ github.event.number }} - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: docs-cache - name: Cache webpack - with: - path: '.cache' - key: ${{ runner.os }}-v4-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - name: Build docs - run: yarn build:docs - - name: Upload docs - run: node .github/upload-preview.js packages/react-docs/public - if: always() - # - name: a11y tests - # run: yarn serve:docs & yarn test:a11y - # - name: Upload a11y results - # run: node .github/upload-preview.js packages/react-docs/coverage - # if: always() - demo_app: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: build - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - name: Build demo app - run: yarn build:integration - - name: Upload demo app - uses: actions/upload-artifact@v2 - with: - name: demo-app - path: packages/react-integration/demo-app-ts/public - test_integration: - runs-on: ubuntu-latest - env: - GH_PR_NUM: ${{ github.event.number }} - needs: demo_app - strategy: - fail-fast: false - matrix: - worker_num: [0, 1, 2, 3, 4] - worker_count: [5] - steps: - - uses: actions/checkout@v2 - # Yes, we really want to checkout the PR - - run: | - if [[ ! -z "${GH_PR_NUM}" ]]; then - echo "Checking out PR" - git fetch origin pull/$GH_PR_NUM/head:tmp - git checkout tmp - fi - - uses: actions/setup-node@v1 - with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist - with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' - - name: Download demo app - uses: actions/download-artifact@v2 - with: - name: demo-app - path: packages/react-integration/demo-app-ts/public - - run: printenv - - name: Cypress tests - run: yarn serve:integration & yarn test:integration -s $(node .github/split.js) - env: - WORKER_NUM: ${{ matrix.worker_num }} - WORKER_COUNT: ${{ matrix.worker_count }} + name: Documentation + uses: ./.github/workflows/documentation.yml + secrets: inherit + deploy: + name: Deploy release runs-on: ubuntu-latest - needs: [lint, test_jest, docs, test_integration] - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - GH_TOKEN: ${{ secrets.GH_TOKEN_REDALLEN }} # needs to be an admin token to get around branch protection - GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }} + needs: [ci, docs] steps: - - uses: actions/checkout@v2 - with: - token: ${{ secrets.GH_TOKEN_REDALLEN }} # needs to be an admin token to get around branch protection - - uses: actions/setup-node@v1 + - name: Check out project + uses: actions/checkout@v4 with: - node-version: '14' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps - with: - path: | - node_modules - **/node_modules - ~/.cache/Cypress - key: ${{ runner.os }}-yarn-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock') }} - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - uses: actions/cache@v2 - id: dist - name: Cache dist + # Fetch all history for all branches and tags, which is needed for the release script. + fetch-depth: 0 + # Pass in an administrator token to get around branch protection. + token: ${{ secrets.GH_TOKEN_REDALLEN }} + + - name: Set up and build project + uses: ./.github/actions/setup-project with: - path: | - packages/*/dist - packages/react-styles/css - key: ${{ runner.os }}-dist-14-${{ secrets.CACHE_VERSION }}-${{ hashFiles('yarn.lock', 'package.json', 'packages/*/*', '!packages/*/dist', '!packages/*/node_modules') }} - - name: Build dist - run: yarn build && yarn build:umd - if: steps.dist.outputs.cache-hit != 'true' + skip-build-cache: true + - name: Deploy to NPM and Github run: .github/release.sh - + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }} + \ No newline at end of file diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000000..ad0513875e2 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,16 @@ +name: Close stale issues and PRs +on: + schedule: + - cron: 37 11 * * * +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + days-before-stale: 60 + days-before-close: -1 + exempt-issue-labels: breaking change :boom:,pinned + stale-issue-label: stale + stale-issue-message: This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. + stale-pr-message: This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. diff --git a/.gitignore b/.gitignore index 6ad8d9efed1..07168936c32 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ coverage .cache .tmp .eslintcache +package-lock.json # package managers yarn-error.log @@ -30,3 +31,4 @@ lerna-debug.log .vscode # For vim *.swp +.yarn diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000000..081c653b345 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +yarn exec lint-staged diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000000..2adc63e5c96 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +# Generated icon files - these are auto-generated and should not be formatted +packages/react-icons/scripts/icons/rhIcons*.mjs +packages/react-icons/scripts/icons/rhdsIcons*.mjs + diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 00000000000..3186f3f0795 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/ADVANCED-USAGE-README.md b/ADVANCED-USAGE-README.md deleted file mode 100644 index 88a6ecf801d..00000000000 --- a/ADVANCED-USAGE-README.md +++ /dev/null @@ -1,9 +0,0 @@ -# PatternFly React -This README covers advanced usage topics for PatternFly React users. - -### Table of contents -1. [Applying Overpass Font](#Applying-Overpass-font) -2. [Tree shaking](#Tree-shaking) - -## Applying Overpass font -If you would like to use Overpass instead of the Red Hat font, simply add the class `.pf-m-overpass-font` to an element that wraps your application (ideally `` or ``) to adopt the CSS changes that would allow opting in to the Overpass font. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6d26e82931c..cb81f3e8134 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,59 +1,85 @@ # Contributing to PatternFly React -> ### Looking for a quick guide to PatternFly 3 React Contribution? [Go Here](https://github.com/patternfly/patternfly-react/blob/patternfly-3/packages/patternfly-react/CONTRIBUTING.md) -> -> ### Looking for a quick guide to PatternFly 4 React Contribution? [Go Here](./packages/react-core/CONTRIBUTING.md) +> **Looking for a quick guide to PatternFly React Contribution?** [Go Here](./packages/react-core/CONTRIBUTING.md) ## Outline +- [Quick Start for New Contributors](#quick-start-for-new-contributors) +- [Community Contributors Hall of Fame](#community-contributors-hall-of-fame) - [Code of Conduct](#code-of-conduct) - [Issues and Project Board](#issues-and-project-board) - [Issue Labels](#issue-labels) - [PR Labels](#pr-labels) - - [Project Board Columns](#project-board-columns) - [Contribution Process](#contribution-process) - [Creating Issues for Bugs](#creating-issues-for-bugs) - [Creating Issues for New Components](#creating-issues-for-new-components) - [Contributing Components](#contributing-components) - [Adding Styling for your Components](#adding-styling-for-your-components) - - [Using Generators](#using-generators) + - [Guidelines and Requirements](#guidelines-and-requirements) - [React Component Requirements](#react-component-requirements) - [Code Consistency](#code-consistency) - [Code Contribution Guidelines](#code-contribution-guidelines) +- [Troubleshooting](#troubleshooting) - [Becoming a Maintainer](#becoming-a-maintainer) - - [How do I become a maintainer?](how-do-i-become-a-maintainer?) - - [How do I lose maintainers status?](how-do-i-lose-maintainers-status?) - - [Quick Tips for New Maintainers](quick-tips-for-new-maintainers) + - [How do I become a maintainer?](#how-do-i-become-a-maintainer) + - [How do I lose maintainers status?](#how-do-i-lose-maintainers-status) + - [Quick Tips for New Maintainers](#quick-tips-for-new-maintainers) + +## Quick Start for New Contributors + +New to contributing to PatternFly React? Here's how to get started quickly: + +1. **🍴 Fork and Clone**: Fork the repository and clone it locally +2. **📦 Install Dependencies**: Run `yarn install` to install dependencies +3. **🏗️ Build**: Run `yarn build` to build the project +4. **🔍 Find an Issue**: Look for issues labeled [`good first issue`](https://github.com/patternfly/patternfly-react/labels/good%20first%20issue) +5. **🌿 Create a Branch**: Create a new branch for your changes +6. **✅ Test**: Run `yarn test` to ensure tests pass +7. **📝 Submit PR**: Create a pull request with a clear description + +**Need help?** Join us on [PatternFly Slack](https://patternfly.slack.com/) in the `#patternfly-react` channel! + +## Community Contributors Hall of Fame + +We want to recognize and celebrate our amazing community contributors who have made significant contributions to PatternFly React in the past year! 🎉 + +### Top Community Contributors (Last 12 Months as on July 1, 2025) + +The following contributors (excluding PatternFly team members and bots) have made outstanding contributions to the project: + +1. **@Mash707** - 49 contributions +2. **@adamviktora** - 10 contributions +3. **@logonoff** - 5 contributions + +### Notable Contributors -## Code of Conduct +Thank you to all our community contributors for helping make PatternFly React better! Every contribution, whether it's code, documentation, bug reports, or feature requests, helps improve the library for everyone. -This project is governed by the [Contributor Covenant version 1.4][1]. All contributors and participants +*This list is updated periodically and reflects contributions over the past 12 months. If you'd like to join this list, check out our [contribution guidelines](#contribution-process) below!* + +## Code of conduct + +This project is governed by the [Contributor Covenant version 2.1][1]. All contributors and participants agree to abide by its terms. To report violations, send an email to [patternfly@redhat.com][2]. -## Issues and Project Board +## AI-assisted development guidelines + +Please reference [PatternFly's AI-assisted development guidelines](https://github.com/patternfly/.github/blob/main/CONTRIBUTING.md) if you'd like to contribute code generated using AI. -We use issues to track work items, such as bug reports and feature requests. Issues can be found in the [issue tracker](https://github.com/patternfly/patternfly-react/issues) or [project board](https://github.com/patternfly/patternfly-react/projects/1). We use the project board to help visualize and manage status of an issue, and we use labels to help prioritize and identify issues. +## Issues and project board -### Issue Labels +We use issues to track work items, such as bug reports and feature requests. Issues can be found in the [issue tracker](https://github.com/patternfly/patternfly-react/issues) or [project board](https://github.com/orgs/patternfly/projects/7). We use the project board to help visualize and manage status of an issue, and we use labels to help prioritize and identify issues. + +### Issue labels Our issue tracker utilizes several labels to help organize and identify issues. Here's what they represent and how we use them: -- `bug` - A bug is a _demonstrable problem_ that is caused by the code in the repository. Please check if the issue has already been reported before reporting a new bug. -- `duplicate` - A duplicate signifies that another issue encapsulates or restates this issue. Duplicates will be closed and referenced as such. -- `enhancement` - An enhancement is a feature request. Please provide as much detail as possible and consider whether your idea fits the scope and aims of this project. - `breaking change` - this issue warrants a major release and potentially changes APIs for downstream consumers. -- `chore` - this issue improves internal tooling or build processes only. -- `documentation` - this issue affects documentation only. -- `css` - this issue affects CSS or has stylistic changes. - `good first issue` - Issues that are ideal for new contributors. -- `help wanted` - Issues we need or would love help from the community to resolve. -- `pending response` - This label indicates that the issue is awaiting reply from a contributor or a maintainer. -- `question` - Use the question label to indicate you are having a problem with something and would like feedback from the community. - `wontfix` - The issue is legitimate, but it is not something the team is currently able or willing to fix or implement. Issues with this label may be revisited in the future. -- `p1`, `p2`, `p3` - These are priority labels. -### PR Labels +### PR labels Since the components in patternfly-react are based on patternfly, we want to make sure these components stay in sync with the core patternfly components as documented on [patternfly.org](http://www.patternfly.org/pattern-library/). To help make sure component contributions are consistent with the [design documentation](http://www.patternfly.org/pattern-library/) and [html/css implementation](https://rawgit.com/patternfly/patternfly/master-dist/dist/tests/), we use the following labels during the PR review process. @@ -62,30 +88,13 @@ Since the components in patternfly-react are based on patternfly, we want to mak - `css approved` - The issue has been reviewed and approved by a member of the css team. - `ux approved` - The issue has been reviewed and approved by a member of the ux team. -The following labels also can be used to improve PatternFly React's [CHANGELOG.md](./CHANGELOG.md) when submitting PRs: - -- `bug` - this PR resolves a bug issue. Releasing will cause a patch level semantic version change. -- `enhancement` - this PR adds a new feature and closes an `enhancement` issue. Releasing will cause a minor semantic version change. -- `breaking change` - this PR warrants a major release and potentially changes APIs for downstream consumers. Releasing will cause a major semantic version change. -- `chore` - this PR improves internal tooling or build processes only. These PRs do not effect release. -- `documentation` - this PR affects documentation only. These PRs do not effect release. -- `css` - this PR affects CSS or has minimal stylistic changes. Releasing will cause a patch level semantic version change. - -### Project Board Columns +### Integration with Jira -The project board uses the following columns to track issues: +We sync our issues to PatternFly's private Jira board. Once an issue is sync'd, a link is added to the issue description in GitHub if someone were to want to track the Jira ticket. Any issue can be assigned an assignee in GitHub or Jira and that information will be sync'd. If an issue is closed in Jira, it will also be closed in GitHub. -- `Backlog` - Issues that are ready to be worked and available for any contributor to take. -- `Needs CSS/Design/Research` - Issues that require any work that would be completed outside of this repo related to css, design or research. For example some component contributions will require updates to css in the core [patternfly](https://github.com/patternfly/patternfly) repo. -- `Assigned` - Issues that are ready to be worked and are already assigned. -- `In Progress` - Issues that are actively being worked. -- `PR in Review` - Issues for which a PR is open and are ready for review. +## Contribution process -Issues can be manually added to the project board from either the issue page or the project board page. - -## Contribution Process - -### Creating Issues for Bugs +### Creating issues for bugs If you find a bug within the repo, please help us track the issue by following these steps: @@ -93,24 +102,22 @@ If you find a bug within the repo, please help us track the issue by following t - If it does exist, but doesn’t capture key details that you have noticed, please add a comment to the existing bug. 2. Create an issue if one doesn’t already exist. - Provide details like what component is affected, steps to reproduce, and any other information that is critical to addressing the issue - - Assign the label “bug” to the issue -### Creating Issues for New Components +### Creating issues for new components To create an issue for adding a new component to the repo, please observe the following process: 1. If the component does not yet exist as a PatternFly component, please do not start coding yet. Components contributed to PatternFly-React should have a design pattern in PatternFly or be approved PatternFly-Extension components. 2. If the component exists in PatternFly core (meaning CSS and the pattern design exists), then create an issue with the following details: - - Assign the label `enhancement` to the issue - Include the text “Component -“ in the beginning of the title if the issue captures a new component - - If the component is documented as a [PatternFly Library Pattern](http://www.patternfly.org/pattern-library/), include a link to it. + - If the component is documented as a [PatternFly library pattern](http://www.patternfly.org/pattern-library/), include a link to it. 3. If a component is not in PatternFly, but you feel it would be a good addition to the library, please do the following: - Open a new GitHub issue and tag it with the Extension label - Reach out on the patternfly-react channel on slack, the mailing list or the forum to see if the issue is approved as an extension - If it is approved, direction will be given as to which package it will go in. Generally, we are recommending most extension components go in individual packages. Several smaller common components may end up being grouped together. In the future, a generator for extension component packages will be created. - Extension components do not undergo the same rigorous design or coding review process as core PatternFly components. If enough members of the community find them useful, we will work to move them into our core PatternFly system by starting the design process for the idea. -### Contributing Components +### Contributing components Components that are ready to be contributed can be found on the project board in the backlog column. They are identified with the text “Component” in the issue title. @@ -125,7 +132,7 @@ Once you’ve identified a component to contribute, component contributions shou If you submit a pull request, then please also contribute by reviewing other pull requests. Please remember that reviewing other contributions is just as important! -### Adding Styling for your Components +### Adding styling for your components Ideally, all the styles that are needed for the components in patternfly-react would be defined in the core [patternfly](https://github.com/patternfly/patternfly) repo. However, there may be cases where additional styles are needed to complete the patternfly-react component contribution. In the case where the styles are specific to the component implementation in the patternfly-react repo, then the styles would remain in the repo. In the case where the component does not exist yet in the core pattenrfly repo and styles are needed for the component in the patternfly-react repo, then the styles would only remain in the patternfly-react repo until the component is added to the core patternfly repo. Once the styles are available as part of core patternfly repo, it will be removed from the patternfly-react repo. @@ -138,27 +145,11 @@ Inside the package directory: - Add a Sass file to the `sass/patternfly-react/` directory and use the file name `_.scss` - Import the Sass file into `sass/patternfly-react/_patternfly-react.scss` using `@import "";` -### Using Generators - -To make contributing components and packages easier a generator utility has been provided. - -To start the generator run: - -```bash -yarn generate -``` - -Follow the prompts to generate the desired component or package. - -Currently the following generators are provided -- PatternFly 4 Component -- PatternFly 3 Component (only available on the `patternfly-3` branch, see [this guide](https://github.com/patternfly/patternfly-react/blob/patternfly-3/packages/patternfly-react/CONTRIBUTING.md)) -- Package -## Guidelines and Requirements +## Guidelines and requirements -### React Component Requirements +### React component requirements Please ensure that all React UI components contributed meet the following guidelines: @@ -168,10 +159,10 @@ Please ensure that all React UI components contributed meet the following guidel - Provide associated examples for documentation in the examples directory for the component. - Provide a [jest snapshot test](https://facebook.github.io/jest/docs/snapshot-testing.html) to ensure your UI markup does not change unexpectedly. - Ensure the component's rendered design and documentation examples meet [PatternFly design standard](https://github.com/patternfly/patternfly-design). - **Note:** If your component does not yet have PatternFly design documentation, the PatternFly React design team will first confirm that the pattern passes the [PatternFly Decision Tree](https://github.com/patternfly/patternfly-design/blob/master/resources/decision-tree/PatternflyDecisionTree.pdf) and then start the process for generating design documentation. + **Note:** If your component does not yet have PatternFly design documentation, the PatternFly React design team will first confirm that the pattern passes the [PatternFly decision tree](https://github.com/patternfly/patternfly-design/blob/master/resources/decision-tree/PatternflyDecisionTree.pdf) and then start the process for generating design documentation. - Ensure the code is properly formatted and there are no linting errors. PatternFly React uses custom eslint configuration based on [Javascript Standard Style](https://standardjs.com/) and [Prettier](https://github.com/prettier/prettier) for code formatting. You can automatically format your code with `yarn prettier` and run the project's linter with `yarn lint`. -### Code Consistency +### Code consistency - All files and folders under your package's `src/components` should name with PascalCase except `index.js` files - If you need a constant file, it should be called `{Component_Name}Constants.js` (Component_Name with PascalCase) @@ -188,76 +179,55 @@ Please ensure that all React UI components contributed meet the following guidel See how to write documentation in the [`react-docs` README](./packages/react-docs/README.md) - When destructuring or spreading expressions , use ...props as the variable name. - **Please see the [Getting Started Readme](./GETTING-STARTED.md) for additional information in getting started with building PatterFly 4 react components.** + **Please see the [getting started README](./GETTING-STARTED.md) for additional information in getting started with building PatterFly react components.** -### Code Contribution Guidelines +### Code contribution guidelines Adhering to the following process is the best way to get your work included in the project: -1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes: - -```bash -# Clone your fork of the repo into the current directory -git clone https://github.com//patternfly-react.git -# Navigate to the newly cloned directory -cd patternfly-react -# Assign the original repo to a remote called "upstream" -git remote add upstream https://github.com/patternfly/patternfly-react.git -# Fetch the code and branches from remote repo "upstream" -git fetch upstream -``` +1. **Fork and set up the repository** ([More information about forks from GitHub](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo)) -2. Create a branch: +2. **Set up your development environment** -```text -$ git checkout -b my-branch upstream/main -``` +**Prerequisites:** +- [Node.js](https://nodejs.org/en/download/package-manager) version 22 or higher +- [Enable Corepack](https://nodejs.org/api/corepack.html) for package manager management +- Git configured with your GitHub account -3. Generate your Component +**Setup commands:** +```sh +# Install dependencies +yarn install -```bash -# Run the tool to Generate the component scaffolding - yarn generate -``` +# Build the project +yarn build -- When you select the option to generate a PatternFly 4 component, a structure resembling the following is generated - ```text - packages/react-core/src/[type]/[ComponentName]/ - index.js - Barrel File exporting public exports - ComponentName.js - Component Implementation - ComponentName.test.js - Component Tests - ComponentName.md - Component Docs - ``` +# Run tests to verify setup +yarn test -4. Develop your component. After development is complete, run build and ensure tests and lint standards pass. - -```text -$ yarn build -$ yarn test +# Start development server (optional) +yarn start ``` -Ensure no lint errors are introduced in `yarn-error.log` after running this command. - -5. Add a commit using `git commit`: - -This project uses [`lerna`](https://lernajs.io/) to do automatic releases and generate a changelog based on the commit history. So we follow [a convention][3] for commit messages. Please follow this convention for your commit messages. - -6. Rebase +**Verify your setup:** +- All tests should pass +- Build should complete without errors +- Development server should start (if running yarn start) -Use `git rebase` (not `git merge`) to sync your work from time to time. Ensure all commits related to a single issue have been [squashed](https://github.com/ginatrapani/todo.txt-android/wiki/Squash-All-Commits-Related-to-a-Single-Issue-into-a-Single-Commit). +3. **Develop your component** - After development is complete, run build and ensure tests and lint standards pass. -```text -$ git fetch upstream -$ git rebase upstream/main +```sh +yarn build +yarn test ``` -7. Push +Ensure no lint errors are introduced in `yarn-error.log` after running this command. -```text -$ git push origin my-branch -``` +***Note to Windows users:*** you may need to change the path for the lint script in package.json to be `node_modules/eslint/bin/eslint` + +4. **Follow commit conventions** - This project uses [`lerna`](https://lernajs.io/) to do automatic releases and generate a changelog based on the commit history. So we follow [conventional commit formatting](https://www.conventionalcommits.org/en/v1.0.0/) for all commit messages. Please follow this convention for your commit messages. -8. Create a Pull Request +5. **Create a pull request** [Open a pull request](https://help.github.com/articles/using-pull-requests/) with a clear title and description against the `main` branch. Please be sure to include all of the following in your PR: @@ -271,7 +241,7 @@ Once your pull request has been reviewed, if all conditions above have been met Please help in ensuring all relevant issues are closed and that any subsequent issues needed have been noted with this pull request. -### Guidelines for React implementation from Core +### Guidelines for React implementation from core - PF-React components should demonstrate all states implemented in Core without adding any new states. - If a new state is introduced in PF-React, it should not be accepted by the reviewer until an issue is created explaining why this example/modification is needed in Core and PF-React. Tag a UX/UI designer. @@ -280,7 +250,36 @@ Please help in ensuring all relevant issues are closed and that any subsequent i - If an issue in Core will affect a component in PF-React, this issue should link to the main PF-React issue. - The CSS Developers and UX Designers should be tagged to review their respective PF-React issue. -## Becoming a Maintainer +## Troubleshooting + +### Common Issues and Solutions + +**Build Failures:** +- Ensure you're using Node.js version 22 or higher: `node --version` +- Clear node_modules and reinstall: `rm -rf node_modules && yarn install` +- Clear yarn cache: `yarn cache clean` + +**Test Failures:** +- Run tests in watch mode for debugging: `yarn test --watch` +- Update snapshots if components have intentionally changed: `yarn test -u` + +**Linting Errors:** +- Auto-fix linting issues: `yarn lint --fix` +- Format code with Prettier: `yarn prettier` + +**Development Server Issues:** +- Clear cache and restart: `rm -rf node_modules/.cache && rm -rf packages/react-docs/.cache && yarn start` + +**Integration Issues:** +- Ensure your branch is up to date with the latest changes before submitting PR +- Squash commits related to a single issue before submitting + +**Still having issues?** +- Check existing [GitHub issues](https://github.com/patternfly/patternfly-react/issues) +- Ask for help in [PatternFly Slack](https://patternfly.slack.com/) `#patternfly-react` channel +- Create a new issue with detailed error information + +## Becoming a maintainer The documentation for becoming a maintainer has been taken from [Foreman](https://theforeman.org/handbook.html#Becomingamaintainer) and adapted for the PatternFly project. @@ -331,6 +330,7 @@ The process for revoking someone's maintainer status is a discussion limited to - Do not merge commits blindly. If you do not fully understand a pull request, ask existing maintainers to take a look - Do not merge if the build is failing. Wait until tests are green to merge. -[1]: http://contributor-covenant.org/version/1/4/code-of-conduct.md +[1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/ [2]: mailto:patternfly@redhat.com [3]: https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#type + diff --git a/GETTING-STARTED.md b/GETTING-STARTED.md index 877bc0973ed..abd574d3573 100644 --- a/GETTING-STARTED.md +++ b/GETTING-STARTED.md @@ -21,11 +21,11 @@ When writing examples: ## Testing -PatternFly React currently uses [Jest](https://facebook.github.io/jest/) for running snapshot tests and [Cypress](https://www.cypress.io/) for running integration tests. +PatternFly React currently uses [Jest](https://facebook.github.io/jest/) with [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) for running unit tests and [Cypress](https://www.cypress.io/) for running integration tests. -### Jest +### Jest + React Testing Library -Use Jest tests to capture how the DOM should look after rendering. Save Jest tests (`*.test.tsx` files) under a `__tests__` folder. The most commonly used test is to expect a rendered component to match a snapshot. You can run these with `yarn test`. +Use Jest and React Testing Library to capture how the DOM should look after rendering and verify that it functions as you expect. Save tests (`*.test.tsx` files) under a `__tests__` folder. A common test is to expect a rendered component to match a snapshot. You can run these with `yarn test`. You can find more information about React Testing Library as it pertains to this project and the standards we're following on our [React Testing Library Basics](https://github.com/patternfly/patternfly-react/wiki/React-Testing-Library-Basics,-Best-Practices,-and-Guidelines) wiki article. ### Cypress @@ -38,7 +38,3 @@ PatternFly React has 3 linters you can run all at once using `yarn lint:all`. Th ### ESLint ESLint is run on .js, .jsx, .ts, and .tsx files. It uses the [@typescript-eslint](https://github.com/typescript-eslint/typescript-eslint) parser with custom config added over the years. We write some of our own ESLint rules in `eslint-plugin-patternfly-react`. You can run this linter with `yarn lint:ts` or on specific files with `yarn lint `. - -### Version lint - -The `@patternfly` version linter is run on all `package.json` files to ensure that versions of all `@patternfly/*` packages match. This is done to prevent mismatching versions of essential PatternFly packages from accidentally being published. You can run this linter with `yarn lint:versions`. diff --git a/README.md b/README.md index 7053a768d5b..6ad8857abff 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@ # PatternFly React - + [![lerna](https://img.shields.io/badge/maintained%20with-lerna-green.svg?style=for-the-badge)](https://lernajs.io/) -[![PatternFly 4 npm badge](https://img.shields.io/npm/v/@patternfly/react-core.svg?label=PF4%20Core&style=for-the-badge)](https://www.npmjs.com/package/@patternfly/react-core) +[![PatternFly npm badge](https://img.shields.io/npm/v/@patternfly/react-core.svg?label=PF%20Core&style=for-the-badge)](https://www.npmjs.com/package/@patternfly/react-core) This project provides a set of React components for the [PatternFly project](https://patternfly.org). **Community:** [PatternFly website](https://www.patternfly.org) | [Slack](https://slack.patternfly.org) | [Medium](https://medium.com/patternfly) | [Mailing list](https://www.redhat.com/mailman/listinfo/patternfly) - + ### Table of contents 1. [PatternFly React packages](#patternfly-react-packages) 2. [Setup](#Setup) 3. [Contribution guidelines](#Contribution-guidelines) -4. [License](#License) +4. [License](#License) -Using PatternFly 3? Take a look at the [PatternFly 3 React component information](https://github.com/patternfly/patternfly-react/blob/patternfly-3/README.md). +Using PatternFly 3? Take a look at the [PatternFly 3 React component information](https://github.com/patternfly/patternfly-react/blob/patternfly-3/README.md). ### PatternFly React packages - + | Package link | Description | | --- | --- | | **:blue_heart: Core packages** | @@ -26,28 +26,25 @@ Using PatternFly 3? Take a look at the [PatternFly 3 React component informatio |   [@patternfly/react-icons](./packages/react-icons/README.md) | Icon components | |   [@patternfly/react-styles](./packages/react-styles/README.md) | PatternFly CSS styles | |   [@patternfly/react-tokens](./packages/react-tokens/README.md) | PatternFly CSS variable tokens | -| **:yellow_heart: Extension packages** *UXD supported* | -|   [@patternfly/react-log-viewer](./packages/react-log-viewer/README.md) | Virtualized log viewer component | +| **:yellow_heart: Extension packages** | +|   [@patternfly/react-log-viewer](https://github.com/patternfly/react-log-viewer/blob/main/README.md) | Virtualized log viewer component | +|   [@patternfly/react-catalog-view-extension](https://github.com/patternfly/react-catalog-view/blob/main/README.md) | Catalog view extension | +|   [@patternfly/react-topology](https://github.com/patternfly/react-topology/blob/main/README.md) | Topology components | | **:open_file_folder: Supporting packages** | |   [@patternfly/react-docs](./packages/react-docs/README.md) | Gatsby documentation site for components | |   [@patternfly/react-integration](./packages/react-integration/README.md) | Cypress integration tests | -| **:family: Extension packages** *community supported* | -|   [@patternfly/react-catalog-view-extension](./packages/react-catalog-view-extension/README.md) | Catalog view extension | -|   [@patternfly/react-virtualized-extension](./packages/react-virtualized-extension/README.md) | Table and list row virtualization extension | -|   [@patternfly/react-topology](./packages/react-topology/README.md) | Topology components | -|   [@patternfly/react-console](./packages/react-console/README.md) | Console components | | **:x: Deprecated packages** | -|   [@patternfly/react-inline-edit-extension](./packages/react-inline-edit-extension/README.md) | Table inline edit extension | +|   [@patternfly/react-virtualized-extension](https://github.com/patternfly/react-virtualized-extension/blob/main/README.md) | Table and list row virtualization extension | -### Setup +### Setup -Before you begin, check out this [overview of PatternFly](http://patternfly.org/v4/get-started/about) to get familiar with the basic elements of the design system. +Before you begin, check out this [overview of PatternFly](http://patternfly.org/get-started/about) to get familiar with the basic elements of the design system. #### Install a package manager Install a package manager before using the PatternFly libraries. -* [Use npm](https://nodejs.org/en/download) -* [Use Yarn](https://yarnpkg.com/en/docs/getting-started) +* [Use npm](https://nodejs.org/en/download/package-manager) +* [Use Yarn](https://yarnpkg.com/getting-started/install) #### Start with PatternFly React seed @@ -72,7 +69,7 @@ If you want to start with your existing project, skip to [Install and configure ``` npm install @patternfly/react-core --save ``` - + **OR** * Using yarn, run the following command to install: @@ -83,7 +80,8 @@ If you want to start with your existing project, skip to [Install and configure Once the library is installed, use the specific setup instructions for that library to access the components it contains. These can be found in the readme for each [library](#patternfly-react-packages). ### Contribution guidelines -All React contributors must first be [PatternFly community contributors](https://www.patternfly.org/v4/contribute/about). If you're already a PatternFly community contributor, check out the [React contribution guidelines](https://github.com/patternfly/patternfly-react/tree/main/CONTRIBUTING.md) to make React contributions. +All React contributors must first be [PatternFly community contributors](https://www.patternfly.org/get-started/contribute/contributing-to-patternfly). If you're already a PatternFly community contributor, check out the [React contribution guidelines](https://github.com/patternfly/patternfly-react/tree/main/CONTRIBUTING.md) to make React contributions. ### License PatternFly React is licensed under the [MIT License](https://github.com/patternfly/patternfly-react/tree/main/LICENSE). + diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md deleted file mode 120000 index 9a251f8b3f6..00000000000 --- a/RELEASE-NOTES.md +++ /dev/null @@ -1 +0,0 @@ -packages/react-docs/RELEASE-NOTES.md \ No newline at end of file diff --git a/UPGRADE-GUIDE.md b/UPGRADE-GUIDE.md deleted file mode 120000 index 270cde92801..00000000000 --- a/UPGRADE-GUIDE.md +++ /dev/null @@ -1 +0,0 @@ -packages/react-docs/UPGRADE-GUIDE.md \ No newline at end of file diff --git a/babel.config.js b/babel.config.js index c03fd5c5ab3..48db1c06484 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,20 +1,4 @@ module.exports = { - presets: [ - [ - '@babel/preset-env', - { - targets: { - esmodules: true - } - } - ], - '@babel/preset-typescript', - '@babel/preset-react' - ], - plugins: [ - ['@babel/plugin-proposal-decorators', { legacy: true }], - '@babel/plugin-proposal-optional-chaining', - '@babel/plugin-proposal-class-properties', - '@babel/plugin-proposal-object-rest-spread' - ] + presets: ['@babel/preset-typescript', ['@babel/preset-react', { runtime: 'automatic' }]], + plugins: ['@babel/plugin-transform-modules-commonjs'] }; diff --git a/eslint.config-md.mjs b/eslint.config-md.mjs new file mode 100644 index 00000000000..da009687858 --- /dev/null +++ b/eslint.config-md.mjs @@ -0,0 +1,48 @@ +import markdown from 'eslint-plugin-markdown'; +import patternflyReact from 'eslint-plugin-patternfly-react'; +import react from 'eslint-plugin-react'; +import tseslint from 'typescript-eslint'; + +export default [ + { + ignores: ['.history/*'] + }, + ...markdown.configs.recommended, + { + plugins: { + react, + 'patternfly-react': patternflyReact + }, + languageOptions: { + parser: tseslint.parser + }, + settings: { + react: { + version: 'detect' + } + }, + rules: { + 'eol-last': 'error', + 'spaced-comment': 'error', + 'no-unused-vars': 'off', + 'no-this-before-super': 'error', + 'patternfly-react/import-tokens-icons': 'error', + 'react/jsx-uses-react': 'error', + 'react/jsx-uses-vars': 'error', + 'react/no-unknown-property': 'error', + 'react/jsx-no-undef': 'error', + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'react', + importNames: ['default'], + message: 'Please use named imports when importing from React.' + } + ] + } + ] + } + } +]; diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000000..567da2b099c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,183 @@ +import { fixupPluginRules } from '@eslint/compat'; +import js from '@eslint/js'; +import patternflyReact from 'eslint-plugin-patternfly-react'; +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'; +import reactCompiler from 'eslint-plugin-react-compiler'; +import reactHooks from 'eslint-plugin-react-hooks'; +import react from 'eslint-plugin-react'; +import testingLibrary from 'eslint-plugin-testing-library'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; + +export default [ + { + ignores: [ + '**/dist', + '**/css', + 'packages/react-core/src/helpers/Popper/thirdparty', + 'packages/react-docs/patternfly-docs/generated', + 'packages/react-docs/coverage', + '.history/*', + 'packages/react-docs/static', + 'packages/react-docs/public', + '**/.cache' + ] + }, + js.configs.recommended, + ...tseslint.configs.recommended, + react.configs.flat.recommended, + react.configs.flat['jsx-runtime'], + eslintPluginPrettierRecommended, + { + plugins: { + 'patternfly-react': fixupPluginRules(patternflyReact), + 'react-hooks': fixupPluginRules(reactHooks), + 'react-compiler': reactCompiler + }, + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + ...globals.jest + } + }, + settings: { + react: { + version: 'detect' + } + }, + rules: { + ...reactHooks.configs.recommended.rules, + '@typescript-eslint/no-wrapper-object-types': 'off', + '@typescript-eslint/no-empty-object-type': 'off', + '@typescript-eslint/no-unsafe-function-type': 'off', + '@typescript-eslint/no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }], + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/adjacent-overload-signatures': 'error', + '@typescript-eslint/array-type': 'error', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/consistent-type-assertions': 'error', + '@typescript-eslint/consistent-type-definitions': 'error', + '@typescript-eslint/explicit-member-accessibility': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/indent': 'off', + '@typescript-eslint/no-duplicate-enum-values': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-empty-interface': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/no-misused-new': 'error', + '@typescript-eslint/no-namespace': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + caughtErrors: 'none' + } + ], + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/prefer-for-of': 'error', + '@typescript-eslint/prefer-function-type': 'error', + '@typescript-eslint/prefer-namespace-keyword': 'error', + '@typescript-eslint/unified-signatures': 'error', + '@typescript-eslint/explicit-function-return-type': 'off', + 'arrow-body-style': 'error', + camelcase: [ + 'error', + { + ignoreDestructuring: true, + allow: ['^t_[global|chart]', '^chart_'] + // TODO: Remove 'chart_' from the allowed patterns after updating all chart examples to use the 't_chart_' format + } + ], + 'constructor-super': 'error', + curly: 'error', + 'dot-notation': 'error', + eqeqeq: ['error', 'smart'], + 'guard-for-in': 'error', + 'max-classes-per-file': ['error', 1], + 'max-len': 'off', + 'no-nested-ternary': 'error', + 'no-bitwise': 'error', + 'no-caller': 'error', + 'no-cond-assign': 'error', + 'no-console': 'error', + 'no-debugger': 'error', + 'no-empty': 'error', + 'no-eval': 'error', + 'no-new-wrappers': 'error', + 'no-prototype-builtins': 'off', + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'react', + importNames: ['default'], + message: 'Please use named imports when importing from React.' + } + ] + } + ], + 'no-shadow': 'off', + 'no-throw-literal': 'error', + 'no-trailing-spaces': 'off', + 'no-undef-init': 'error', + 'no-constant-binary-expression': 'off', + 'no-unsafe-finally': 'error', + 'no-unused-expressions': [ + 'error', + { + allowTernary: true, + allowShortCircuit: true + } + ], + 'no-unused-labels': 'error', + 'no-var': 'error', + 'object-shorthand': 'error', + 'one-var': ['error', 'never'], + 'patternfly-react/import-tokens-icons': 'error', + 'patternfly-react/no-anonymous-functions': 'error', + 'prefer-const': 'error', + radix: ['error', 'as-needed'], + 'react/prop-types': 0, + 'react/display-name': 0, + 'react-compiler/react-compiler': 'warn', + 'react-hooks/exhaustive-deps': 'warn', + 'react/no-unescaped-entities': ['error', { forbid: ['>', '}'] }], + 'spaced-comment': 'error', + 'use-isnan': 'error', + 'patternfly-react/no-layout-effect': 'error', + 'valid-typeof': 'off' + } + }, + { + files: ['**/examples/*', '**/demos/examples/**/*'], + rules: { + 'patternfly-react/no-anonymous-functions': 'off' + } + }, + { + files: ['**/*.test.[jt]s?(x)'], + plugins: { + 'testing-library': fixupPluginRules(testingLibrary) + }, + rules: { + ...testingLibrary.configs.react.rules, + '@typescript-eslint/no-unused-vars': 'off', + 'testing-library/no-node-access': 'off', + 'react/jsx-key': 'off', + 'react/no-children-prop': 'off', + 'no-console': 'off' + } + }, + { + files: ['packages/react-integration/demo-app-ts/**/*'], + rules: { + 'patternfly-react/no-anonymous-functions': 'off', + 'react/react-in-jsx-scope': 'off', + 'spaced-comment': 'off' + } + } +]; diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index f860c9e2d6c..00000000000 --- a/jest.config.js +++ /dev/null @@ -1,24 +0,0 @@ -module.exports = { - collectCoverage: true, - coverageReporters: ['lcov'], - clearMocks: true, - testMatch: ['**/__tests__/**/*.{js,ts}?(x)', '**/*.test.{js,ts}?(x)'], - modulePathIgnorePatterns: [ - '/packages/*.*/dist/*.*', - '/packages/*.*/public/*.*', - '/packages/*.*/.cache/*.*' - ], - roots: ['/packages'], - setupFiles: ['/jest.env.js'], - snapshotSerializers: ['enzyme-to-json/serializer'], - transform: { - '^.+\\.[jt]sx?$': 'babel-jest' - }, - transformIgnorePatterns: ['node_modules/(?!@patternfly|@novnc|@popperjs|lodash|monaco-editor|react-monaco-editor)'], - testPathIgnorePatterns: ['/packages/react-integration/'], - coveragePathIgnorePatterns: ['/dist/'], - moduleNameMapper: { - '\\.(css|less)$': '/packages/react-styles/__mocks__/styleMock.js' - }, - testEnvironment: 'jsdom' -}; diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000000..7263343f2c9 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,32 @@ +/** + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ +import type { Config } from 'jest'; + +const config: Config = { + collectCoverage: true, + coverageReporters: ['lcov'], + clearMocks: true, + testMatch: ['**/__tests__/**/*.{js,ts}?(x)', '**/*.test.{js,ts}?(x)'], + modulePathIgnorePatterns: [ + '/packages/*.*/dist/*.*', + '/packages/*.*/public/*.*', + '/packages/*.*/.cache/*.*' + ], + roots: ['/packages'], + transform: { + '^.+\\.m?[jt]sx?$': 'babel-jest', + '^.+\\.svg$': 'jest-transform-stub' + }, + setupFilesAfterEnv: ['/packages/testSetup.ts', 'jest-canvas-mock'], + testPathIgnorePatterns: ['/packages/react-integration/'], + transformIgnorePatterns: ['/node_modules/victory-*/', '/node_modules/(?!(case-anything|echarts|zrender)/)'], + coveragePathIgnorePatterns: ['/dist/'], + moduleNameMapper: { + '\\.(css|less)$': '/packages/react-styles/__mocks__/styleMock.js' + }, + testEnvironment: 'jsdom' +}; + +export default config; diff --git a/jest.env.js b/jest.env.js deleted file mode 100644 index 453a1093871..00000000000 --- a/jest.env.js +++ /dev/null @@ -1,10 +0,0 @@ -import 'raf/polyfill'; -import { configure } from 'enzyme'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; -import MutationObserver from 'mutation-observer'; - -configure({ adapter: new Adapter() }); - -// referenced from '@novnc/nvnc/core/util/events.js' -// The MutationObserver is available in supported browsers, this is workaround for "jest" -global.MutationObserver = MutationObserver; diff --git a/lerna.json b/lerna.json index e69c1fbc061..c0c2c7cbe39 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,4 @@ { - "lerna": "3.10.5", "npmClient": "yarn", "publishConfig": { "access": "public", @@ -25,5 +24,7 @@ } }, "version": "independent", - "useWorkspaces": true -} \ No newline at end of file + "allowBranch": ["main", "v4", "5.0.x", "6.3.x", "v5"], + "packages": ["packages/*", "packages/react-integration/demo-app-ts"], + "$schema": "node_modules/lerna/schemas/lerna-schema.json" +} diff --git a/package.json b/package.json index ff202abeacc..f1d16ae8737 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,9 @@ "url": "https://github.com/patternfly/patternfly-react.git" }, "engines": { - "node": ">=14.0.0", - "yarn": ">=1.6.0" + "node": ">=22.17.1" }, + "packageManager": "yarn@4.7.0", "keywords": [ "react", "patternfly", @@ -24,88 +24,103 @@ }, "homepage": "https://github.com/patternfly/patternfly-react#readme", "devDependencies": { - "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-decorators": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.9.0", - "@babel/preset-env": "^7.0.0", - "@babel/preset-react": "^7.0.0", - "@babel/preset-typescript": "^7.9.0", - "@octokit/rest": "^16.43.2", - "@types/enzyme": "3.9.0", - "@types/jest": "27.0.2", - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", - "@typescript-eslint/eslint-plugin": "^4.4.1", - "@typescript-eslint/parser": "^4.4.1", - "@wojtekmaj/enzyme-adapter-react-17": "^0.3.1", - "babel-jest": "^27.2.5", - "concurrently": "^5.3.0", - "enzyme": "3.10.0", - "enzyme-to-json": "3.4.0", - "eslint": "^7.11.0", - "eslint-plugin-markdown": "^1.0.2", - "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.21.4", - "fs-extra": "^6.0.1", - "glob": "^7.1.2", - "husky": "^4.3.0", - "jest": "27.2.5", - "jest-cli": "27.2.5", - "lerna": "^3.19.0", - "lint-staged": "^10.4.2", + "@babel/core": "^7.28.5", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/preset-env": "^7.28.5", + "@babel/preset-react": "^7.28.5", + "@babel/preset-typescript": "^7.28.5", + "@eslint/compat": "^1.4.1", + "@eslint/js": "^9.32.0", + "@octokit/rest": "^21.1.1", + "@rhds/icons": "^2.1.0", + "@rollup/plugin-commonjs": "^26.0.3", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-replace": "^5.0.7", + "@rollup/plugin-terser": "^0.4.4", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", + "@types/jest": "29.5.14", + "@types/node": "^22.16.5", + "@types/react": "^18.3.28", + "@types/react-dom": "^18.3.7", + "babel-jest": "^29.7.0", + "concurrently": "^9.2.1", + "eslint": "^9.32.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-markdown": "^5.1.0", + "eslint-plugin-prettier": "^5.5.5", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-compiler": "19.0.0-beta-ebf51a3-20250411", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-testing-library": "^7.16.2", + "fs-extra": "^11.3.3", + "glob": "^11.1.0", + "globals": "^15.15.0", + "husky": "^9.1.7", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jest-transform-stub": "^2.0.0", + "lerna": "^8.2.4", + "lint-staged": "^15.5.2", "mutation-observer": "^1.0.3", - "plop": "^2.0.0", - "prettier": "^1.18.2", - "react": "^17.0.0", - "react-dom": "^17.0.0", - "surge": "^0.21.3", - "ts-patch": "^1.4.2", - "typescript": "^4.0.0" + "plop": "^4.0.5", + "prettier": "^3.8.1", + "publint": "^0.3.18", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "rimraf": "^6.1.3", + "rollup": "^4.57.1", + "rollup-plugin-scss": "^4.0.1", + "rollup-plugin-svg": "^2.0.0", + "sass": "^1.86.0", + "surge": "^0.24.6", + "ts-node": "^10.9.2", + "ts-patch": "^3.3.0", + "typescript": "^5.4.5", + "typescript-eslint": "^8.22.0" }, "scripts": { - "build": "yarn build:generate && yarn build:esm && yarn build:cjs", + "build": "yarn clean && yarn build:generate && yarn build:esm && yarn build:cjs && yarn build:subpaths && yarn build:single:packages", "build:cjs": "tsc --build --verbose packages/tsconfig.cjs.json", "build:esm": "tsc --build --verbose packages/tsconfig.json", - "build:integration": "lerna run build:demo-app --stream", + "build:integration": "lerna run build --scope=demo-app-ts --stream", "build:docs": "yarn workspace @patternfly/react-docs build:docs", "build:generate": "lerna run generate --parallel --stream", + "build:subpaths": "lerna run subpaths --parallel --stream", "build:umd": "lerna run build:umd --parallel --stream", + "build:single:packages": "lerna run build:single:packages", "clean": "yarn clean:build && lerna run clean --parallel", "clean:build": "rimraf .cache .eslintcache coverage", "generate": "yarn plop", - "lint": "node --max-old-space-size=4096 node_modules/.bin/eslint --ext js,jsx,ts,tsx --cache", - "lint:all": "yarn lint:md && yarn lint:versions && yarn lint:ts", - "lint:md": "yarn eslint packages --ext md --no-eslintrc --config .eslintrc-md.json --cache", - "lint:ts": "yarn lint packages", - "lint:versions": "node scripts/verifyPatternflyVersions.js", - "prepare": "ts-patch install -s", + "lint": "eslint . --cache --cache-strategy content", + "lint:all": "yarn lint:md && yarn lint:ts", + "lint:md": "eslint \"**/*.md\" --config eslint.config-md.mjs --cache --cache-strategy content --no-warn-ignored", + "lint:ts": "yarn lint packages/*/src", + "lint:tests": "yarn lint packages/*/src/components/*/__tests__/*.test.*", + "lint:publication": "yarn workspaces foreach --all --no-private --parallel exec publint --strict", + "postinstall": "ts-patch install -s && husky", "serve:docs": "yarn workspace @patternfly/react-docs serve", - "serve:integration": "lerna run serve:demo-app", + "serve:integration": "lerna run preview --scope=demo-app-ts", "start": "yarn build && concurrently --kill-others \"yarn watch\" \"yarn workspace @patternfly/react-docs develop\"", "start:cypress": "lerna run cypress:open", - "start:demo-app": "lerna run start:demo-app --stream", - "test": "jest packages", + "start:demo-app": "lerna run dev --scope=demo-app-ts --stream", + "test": "TZ=EST LC_ALL=en_US.UTF8 jest packages", "test:a11y": "lerna run test:a11y --stream", "test:integration": "yarn workspace @patternfly/react-integration test:integration", "uninstall": "find . -name node_modules -type d | xargs rm -rf", "watch": "yarn build:esm --watch", "screenshots": "yarn workspace @patternfly/react-docs screenshots" }, - "husky": { - "hooks": { - "pre-commit": "lint-staged" - } - }, "lint-staged": { "*.md": "yarn lint:md --fix", - "*.{js,jsx,ts,tsx}": "yarn lint --fix", - "*.json": "yarn lint:versions --fix" + "*.{js,jsx,ts,tsx}": "yarn lint --fix" }, "workspaces": { "packages": [ - "packages/**" + "packages/*", + "packages/react-integration/demo-app-ts" ] } } diff --git a/packages/code-connect/components/AboutModal/AboutModal.figma.tsx b/packages/code-connect/components/AboutModal/AboutModal.figma.tsx new file mode 100644 index 00000000000..fb15f4065b1 --- /dev/null +++ b/packages/code-connect/components/AboutModal/AboutModal.figma.tsx @@ -0,0 +1,63 @@ +import figma from '@figma/code-connect'; +import { AboutModal, Button, Content } from '@patternfly/react-core'; + +/** + * PatternFly AboutModal integration for Figma Code Connect + * @see https://www.patternfly.org/components/about-modal + */ + +figma.connect( + AboutModal, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2879-13973&t=15CEJpGgVui7qP5Q-11', + { + props: { + productName: figma.string('Product name') + }, + example: ({ productName }) => { + /* eslint-disable */ + const [isOpen, setIsOpen] = React.useState(false); + /* eslint-enable */ + + return ( + <> + + setIsOpen(false)} + productName={productName} + trademark="Copyright © 2024" + brandImageSrc="/assets/images/brand.svg" + brandImageAlt="Brand Image Alt Text" + backgroundImageSrc="/assets/images/background.png" + > + +
+
CFME version
+
5.5.3.4.20102789036450
+
Cloudforms Version
+
4.1
+
Server name
+
40DemoMaster
+
User name
+
Administrator
+
User role
+
EvmRole-super_administrator
+
Browser version
+
601.2
+
Browser OS
+
Mac
+
+
+
+ + ); + } + } +); diff --git a/packages/code-connect/components/Accordion/Accordion.figma.tsx b/packages/code-connect/components/Accordion/Accordion.figma.tsx new file mode 100644 index 00000000000..9ef35289b62 --- /dev/null +++ b/packages/code-connect/components/Accordion/Accordion.figma.tsx @@ -0,0 +1,27 @@ +import figma from '@figma/code-connect'; +import { Accordion } from '@patternfly/react-core'; + +// Documentation for Accordion can be found at https://www.patternfly.org/components/accordion + +figma.connect( + Accordion, + 'https://www.figma.com/file/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=2621-623', + { + props: { + // enum + displaySize: figma.enum('Type', { 'Large Bordered': 'lg' }), + isBordered: figma.enum('Type', { + Bordered: true, + 'Large Bordered': true + }), + togglePosition: figma.enum('Caret position', { Left: 'start' }), + + children: figma.children('Accordion toggle') + }, + example: (props) => ( + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/Accordion/AccordionToggle.figma.tsx b/packages/code-connect/components/Accordion/AccordionToggle.figma.tsx new file mode 100644 index 00000000000..4f5708cdb6a --- /dev/null +++ b/packages/code-connect/components/Accordion/AccordionToggle.figma.tsx @@ -0,0 +1,34 @@ +import figma from '@figma/code-connect'; +import { AccordionItem, AccordionToggle, AccordionContent } from '@patternfly/react-core'; + +// Documentation for AccordionToggle can be found at https://www.patternfly.org/components/accordion +// Note: Adding on onClick event is recommended to initialize AccordionToggle + +figma.connect( + AccordionToggle, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1423-687', + { + props: { + // string + expandText: figma.string('Expand Text'), + + // enum + open: figma.enum('State', { Expanded: true }), + toggleTextExpanded: figma.enum('State', { + Default: figma.string('Toggle Text'), + Hover: figma.string('Toggle Text'), + Expanded: figma.string('Toggle Text Expanded') + }) + }, + example: (props) => ( + + {}} id=""> + {props.toggleTextExpanded} + + +

{props.expandText}

+
+
+ ) + } +); diff --git a/packages/code-connect/components/ActionList/ActionList.figma.tsx b/packages/code-connect/components/ActionList/ActionList.figma.tsx new file mode 100644 index 00000000000..e92199479ab --- /dev/null +++ b/packages/code-connect/components/ActionList/ActionList.figma.tsx @@ -0,0 +1,20 @@ +import figma from '@figma/code-connect'; +import { ActionList } from '@patternfly/react-core'; + +// TODO: DESIGN: Add ActionListGroup component +// TODO: DESIGN: Add ActionListItem component +// Documentation for ActionList can be found at https://www.patternfly.org/components/action-list + +figma.connect( + ActionList, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=6780-15839', + { + props: { + // enum + isIconList: figma.enum('Type', { 'Action icons only': true }), + + children: figma.children('*') + }, + example: (props) => {props.children} + } +); diff --git a/packages/code-connect/components/Alert/InlineAlert.figma.tsx b/packages/code-connect/components/Alert/InlineAlert.figma.tsx new file mode 100644 index 00000000000..e78a587fa5e --- /dev/null +++ b/packages/code-connect/components/Alert/InlineAlert.figma.tsx @@ -0,0 +1,33 @@ +import figma from '@figma/code-connect'; +import { Alert } from '@patternfly/react-core'; + +// Documentation for Alert can be found at https://www.patternfly.org/components/alert + +figma.connect( + Alert, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1110-2698', + { + props: { + // string + description: figma.string('✏️ Title'), + title: figma.string('✏️ Title'), + + // boolean + isExpandable: figma.boolean('Expandable'), + + // enum + variant: figma.enum('Type', { + Info: 'info', + Success: 'success', + Warning: 'warning', + Danger: 'danger', + Custom: 'custom' + }) + }, + example: (props) => ( + + {props.description} + + ) + } +); diff --git a/packages/code-connect/components/Alert/InlineAlertGroup.figma.tsx b/packages/code-connect/components/Alert/InlineAlertGroup.figma.tsx new file mode 100644 index 00000000000..cefe226d00b --- /dev/null +++ b/packages/code-connect/components/Alert/InlineAlertGroup.figma.tsx @@ -0,0 +1,19 @@ +import figma from '@figma/code-connect'; +import { AlertGroup } from '@patternfly/react-core'; + +// Documentation for Alert can be found at https://www.patternfly.org/components/alert + +figma.connect( + AlertGroup, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1110-2780', + { + props: { + children: figma.children('*') + }, + example: (props) => ( + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/Alert/InlinePlainAlert.figma.tsx b/packages/code-connect/components/Alert/InlinePlainAlert.figma.tsx new file mode 100644 index 00000000000..2da8fbeb2e7 --- /dev/null +++ b/packages/code-connect/components/Alert/InlinePlainAlert.figma.tsx @@ -0,0 +1,32 @@ +import figma from '@figma/code-connect'; +import { Alert } from '@patternfly/react-core'; + +// Documentation for Alert can be found at https://www.patternfly.org/components/alert + +figma.connect( + Alert, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1110-2754', + { + props: { + // string + description: figma.string('✏️ Title'), + title: figma.string('✏️ Title'), + + // enum + variant: figma.enum('Type', { + Info: 'info', + Success: 'success', + Warning: 'warning', + Danger: 'danger', + Custom: 'custom' + }), + + children: figma.children('*') + }, + example: (props) => ( + + {props.description} + + ) + } +); diff --git a/packages/code-connect/components/Alert/OverflowFooter.figma.tsx b/packages/code-connect/components/Alert/OverflowFooter.figma.tsx new file mode 100644 index 00000000000..04a73853b41 --- /dev/null +++ b/packages/code-connect/components/Alert/OverflowFooter.figma.tsx @@ -0,0 +1,42 @@ +import figma from '@figma/code-connect'; +import { Alert, AlertActionCloseButton, AlertGroup } from '@patternfly/react-core'; + +// Documentation for Alert can be found at https://www.patternfly.org/components/alert + +figma.connect( + AlertGroup, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1110-2784', + { + props: { + overflowMessage: figma.string('✏️ Title') + }, + example: (props) => ( + {}} overflowMessage={props.overflowMessage}> + {}} />} + key={1} + /> + {}} />} + key={2} + /> + {}} />} + key={3} + /> + {}} />} + key={4} + /> + + ) + } +); diff --git a/packages/code-connect/components/Alert/ToastAlert.figma.tsx b/packages/code-connect/components/Alert/ToastAlert.figma.tsx new file mode 100644 index 00000000000..b7d1ef87d50 --- /dev/null +++ b/packages/code-connect/components/Alert/ToastAlert.figma.tsx @@ -0,0 +1,40 @@ +import figma from '@figma/code-connect'; +import { Alert } from '@patternfly/react-core'; + +// Documentation for Alert can be found at https://www.patternfly.org/components/alert + +figma.connect( + Alert, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1110-2587', + { + props: { + // string + description: figma.string('✏️ Title'), + title: figma.string('✏️ Title'), + + // boolean + isExpandable: figma.boolean('Expandable'), + + // enum + variant: figma.enum('Type', { + Custom: 'custom', + Danger: 'danger', + Info: 'info', + Success: 'success', + Warning: 'warning' + }) + }, + example: (props) => ( + + {props.description} + + ) + } +); diff --git a/packages/code-connect/components/Alert/ToastAlertGroup.figma.tsx b/packages/code-connect/components/Alert/ToastAlertGroup.figma.tsx new file mode 100644 index 00000000000..7a16c09a440 --- /dev/null +++ b/packages/code-connect/components/Alert/ToastAlertGroup.figma.tsx @@ -0,0 +1,19 @@ +import figma from '@figma/code-connect'; +import { AlertGroup } from '@patternfly/react-core'; + +// Documentation for AlertGroup can be found at https://www.patternfly.org/components/alert + +figma.connect( + AlertGroup, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1110-2821', + { + props: { + children: figma.children('*') + }, + example: (props) => ( + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/Avatar/Avatar.figma.tsx b/packages/code-connect/components/Avatar/Avatar.figma.tsx new file mode 100644 index 00000000000..8959f3c1c9c --- /dev/null +++ b/packages/code-connect/components/Avatar/Avatar.figma.tsx @@ -0,0 +1,26 @@ +import figma from '@figma/code-connect'; +import { Avatar } from '@patternfly/react-core'; + +// Documentation for Avatar can be found at https://www.patternfly.org/components/avatar + +figma.connect( + Avatar, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=1561-4342', + { + props: { + // boolean + isBordered: figma.boolean('Bordered'), + + // enum + size: figma.enum('Size', { + small: 'sm', + med: 'md', + lg: 'lg', + XL: 'xl' + }) + }, + example: (props) => ( + + ) + } +); diff --git a/packages/code-connect/components/BackToTop/BackToTop.figma.tsx b/packages/code-connect/components/BackToTop/BackToTop.figma.tsx new file mode 100644 index 00000000000..c6c58f7724e --- /dev/null +++ b/packages/code-connect/components/BackToTop/BackToTop.figma.tsx @@ -0,0 +1,15 @@ +import figma from '@figma/code-connect'; +import { BackToTop } from '@patternfly/react-core'; + +// Documentation for BackToTop can be found at https://www.patternfly.org/components/back-to-top + +figma.connect( + BackToTop, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1521-958', + { + props: { + text: figma.string('Text') + }, + example: (props) => + } +); diff --git a/packages/code-connect/components/Backdrop/Backdrop.figma.tsx b/packages/code-connect/components/Backdrop/Backdrop.figma.tsx new file mode 100644 index 00000000000..3c6e02acc70 --- /dev/null +++ b/packages/code-connect/components/Backdrop/Backdrop.figma.tsx @@ -0,0 +1,12 @@ +import figma from '@figma/code-connect'; +import { Backdrop } from '@patternfly/react-core'; + +// Documentation for Backdrop can be found at https://www.patternfly.org/components/backdrop + +figma.connect( + Backdrop, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=2873-2900', + { + example: () => + } +); diff --git a/packages/code-connect/components/BackgroundImage/BackgroundImage.figma.tsx b/packages/code-connect/components/BackgroundImage/BackgroundImage.figma.tsx new file mode 100644 index 00000000000..bc8654807bc --- /dev/null +++ b/packages/code-connect/components/BackgroundImage/BackgroundImage.figma.tsx @@ -0,0 +1,12 @@ +import figma from '@figma/code-connect'; +import { BackgroundImage } from '@patternfly/react-core'; + +// Documentation for BackgroundImage can be found at https://www.patternfly.org/components/background-image + +figma.connect( + BackgroundImage, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2722-13543', + { + example: () => + } +); diff --git a/packages/code-connect/components/Badge/Badge.figma.tsx b/packages/code-connect/components/Badge/Badge.figma.tsx new file mode 100644 index 00000000000..d45e66a0a9a --- /dev/null +++ b/packages/code-connect/components/Badge/Badge.figma.tsx @@ -0,0 +1,24 @@ +import figma from '@figma/code-connect'; +import { Badge } from '@patternfly/react-core'; + +// Documentation for Badge can be found at https://www.patternfly.org/components/badge + +figma.connect( + Badge, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1259-1132', + { + props: { + // string + text: figma.string('Text'), + + // enum + isDisabled: figma.enum('Type', { disabled: true }), + isRead: figma.enum('Type', { Read: true }) + }, + example: (props) => ( + + {props.text} + + ) + } +); diff --git a/packages/code-connect/components/Banner/NonStatusBanner.figma.tsx b/packages/code-connect/components/Banner/NonStatusBanner.figma.tsx new file mode 100644 index 00000000000..5b11678d0c7 --- /dev/null +++ b/packages/code-connect/components/Banner/NonStatusBanner.figma.tsx @@ -0,0 +1,28 @@ +import figma from '@figma/code-connect'; +import { Banner } from '@patternfly/react-core'; + +// Documentation for Banner can be found at https://www.patternfly.org/components/banner + +figma.connect( + Banner, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=221-1443', + { + props: { + // string + text: figma.string('✏️ Center text'), + + // enum + color: figma.enum('Color', { + Red: 'red', + Orangered: 'orangered', + Orange: 'orange', + Yellow: 'yellow', + Green: 'green', + Teal: 'teal', + Blue: 'blue', + Purple: 'purple' + }) + }, + example: (props) => {props.text} + } +); diff --git a/packages/code-connect/components/Banner/StatusBanner.figma.tsx b/packages/code-connect/components/Banner/StatusBanner.figma.tsx new file mode 100644 index 00000000000..83272bdd787 --- /dev/null +++ b/packages/code-connect/components/Banner/StatusBanner.figma.tsx @@ -0,0 +1,36 @@ +import figma from '@figma/code-connect'; +import { Banner } from '@patternfly/react-core'; + +// Documentation for Banner can be found at https://www.patternfly.org/components/banner + +figma.connect( + Banner, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=221-937', + { + props: { + // string + text: figma.string('✏️ Center text'), + + // enum + status: figma.enum('Status', { + Success: 'success', + Warning: 'warning', + Danger: 'danger', + Info: 'info', + Custom: 'custom' + }), + screenReaderText: figma.enum('Status', { + Success: 'Success banner screen reader text', + Warning: 'Warning banner screen reader text', + Danger: 'Danger banner screen reader text', + Info: 'Info banner screen reader text', + Custom: 'Custom banner screen reader text' + }) + }, + example: (props) => ( + + {props.text} + + ) + } +); diff --git a/packages/code-connect/components/Brand/FullLogo.figma.tsx b/packages/code-connect/components/Brand/FullLogo.figma.tsx new file mode 100644 index 00000000000..28f7f91f853 --- /dev/null +++ b/packages/code-connect/components/Brand/FullLogo.figma.tsx @@ -0,0 +1,14 @@ +import figma from '@figma/code-connect'; +import { Brand } from '@patternfly/react-core'; + +// Documentation for Brand can be found at https://www.patternfly.org/components/brand + +figma.connect( + Brand, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2104-3689', + { + example: () => ( + + ) + } +); diff --git a/packages/code-connect/components/Brand/MastheadLogo.figma.tsx b/packages/code-connect/components/Brand/MastheadLogo.figma.tsx new file mode 100644 index 00000000000..c78c3da6801 --- /dev/null +++ b/packages/code-connect/components/Brand/MastheadLogo.figma.tsx @@ -0,0 +1,21 @@ +import figma from '@figma/code-connect'; +import { Brand } from '@patternfly/react-core'; + +// Documentation for Brand can be found at https://www.patternfly.org/components/brand + +figma.connect( + Brand, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2104-3644', + { + example: () => ( + + + + + + + + + ) + } +); diff --git a/packages/code-connect/components/Breadcrumbs/Breadcrumb.figma.tsx b/packages/code-connect/components/Breadcrumbs/Breadcrumb.figma.tsx new file mode 100644 index 00000000000..6ad19b534e8 --- /dev/null +++ b/packages/code-connect/components/Breadcrumbs/Breadcrumb.figma.tsx @@ -0,0 +1,15 @@ +import figma from '@figma/code-connect'; +import { Breadcrumb } from '@patternfly/react-core'; + +// Documentation for Breadcrumb can be found at https://www.patternfly.org/components/breadcrumb + +figma.connect( + Breadcrumb, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=3362-283', + { + props: { + children: figma.children('*') + }, + example: (props) => {props.children} + } +); diff --git a/packages/code-connect/components/Breadcrumbs/BreadcrumbItem.figma.tsx b/packages/code-connect/components/Breadcrumbs/BreadcrumbItem.figma.tsx new file mode 100644 index 00000000000..6e834534dcc --- /dev/null +++ b/packages/code-connect/components/Breadcrumbs/BreadcrumbItem.figma.tsx @@ -0,0 +1,22 @@ +import figma from '@figma/code-connect'; +import { BreadcrumbItem } from '@patternfly/react-core'; + +// Documentation for BreadcrumbItem can be found at https://www.patternfly.org/components/breadcrumb + +figma.connect( + BreadcrumbItem, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=3362-74', + { + props: { + // string + text: figma.string('Text'), + + // enum + to: figma.enum('State', { + Link: '#', + Hover: '#' + }) + }, + example: (props) => {props.text} + } +); diff --git a/packages/code-connect/components/Breadcrumbs/ExpandableBreadcrumbs.figma.tsx b/packages/code-connect/components/Breadcrumbs/ExpandableBreadcrumbs.figma.tsx new file mode 100644 index 00000000000..47f48d3ea6a --- /dev/null +++ b/packages/code-connect/components/Breadcrumbs/ExpandableBreadcrumbs.figma.tsx @@ -0,0 +1,70 @@ +import figma from '@figma/code-connect'; +import { Badge, BreadcrumbItem, Dropdown, DropdownItem, DropdownList, Icon, MenuToggle } from '@patternfly/react-core'; +import RhMicronsCaretLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-left-icon'; + +// Documentation for BreadcrumbItem can be found at https://www.patternfly.org/components/breadcrumb + +figma.connect( + BreadcrumbItem, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=19922-43760', + { + props: {}, + example: () => ( + + {}} + onOpenChange={() => {}} + toggle={() => ( + + 01 + + } + onClick={() => {}} + isExpanded={false} + variant="plainText" + /> + )} + isOpen={false} + > + + + + + } + key="edit" + > + Edit + + , + + + + } + key="action" + > + Deployment + + , + + + + } + key="apps" + > + Applications + + + + + ) + } +); diff --git a/packages/code-connect/components/ClipboardCopy/ClipboardCopyBasic.figma.tsx b/packages/code-connect/components/ClipboardCopy/ClipboardCopyBasic.figma.tsx new file mode 100644 index 00000000000..8f5047d7e1c --- /dev/null +++ b/packages/code-connect/components/ClipboardCopy/ClipboardCopyBasic.figma.tsx @@ -0,0 +1,37 @@ +import figma from '@figma/code-connect'; +import { ClipboardCopy } from '@patternfly/react-core'; + +// TODO: DESIGN: ClipboardCopy is using InputGroup improperly. There's no InputGroup wrapper for InputGroupItems + +figma.connect( + ClipboardCopy, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=9914-75835', + { + props: { + // enum + isExpanded: figma.enum('State', { Expanded: true }), + isReadOnly: figma.enum('State', { 'Read only': true }), + expansion: figma.enum('State', { + Expanded: 'expansion', + false: undefined + }), + + inputText: figma.nestedProps('Input Group Items', { + value: figma.string('✏️ Input text') + }) + }, + example: (props) => ( + // Documentation for ClipboardCopy can be found at https://www.patternfly.org/components/clipboard-copy + {}} + clickTip="Copied" + hoverTip="Copy" + isExpanded={props.isExpanded} + isReadOnly={props.isReadOnly} + variant={props.expansion} + > + {props.inputText.value} + + ) + } +); diff --git a/packages/code-connect/components/ClipboardCopy/ClipboardCopyInlineCompact.figma.tsx b/packages/code-connect/components/ClipboardCopy/ClipboardCopyInlineCompact.figma.tsx new file mode 100644 index 00000000000..5a990fae565 --- /dev/null +++ b/packages/code-connect/components/ClipboardCopy/ClipboardCopyInlineCompact.figma.tsx @@ -0,0 +1,19 @@ +import figma from '@figma/code-connect'; +import { ClipboardCopy } from '@patternfly/react-core'; + +// Documentation for ClipboardCopy can be found at https://www.patternfly.org/components/clipboard-copy + +figma.connect( + ClipboardCopy, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=9914-75768', + { + props: { + children: figma.children('*') + }, + example: (props) => ( + {}} variant="inline-compact"> + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/CodeBlock/CodeBlock.figma.tsx b/packages/code-connect/components/CodeBlock/CodeBlock.figma.tsx new file mode 100644 index 00000000000..1f0c5696ec1 --- /dev/null +++ b/packages/code-connect/components/CodeBlock/CodeBlock.figma.tsx @@ -0,0 +1,43 @@ +import figma from '@figma/code-connect'; +import { CodeBlock, CodeBlockCode, ExpandableSection, ExpandableSectionToggle } from '@patternfly/react-core'; + +// TODO: DESIGN: Configure Actions layer to contain CodeBlockAction components + +figma.connect( + CodeBlock, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=9802-5857', + { + props: { + editorText: 'code block code', + + actions: `action1, action2, action3, action4, action5`, + + // boolean + expandableSectionToggle: figma.boolean('Expandable', { + true: ( + {}} contentId="code-block-id"> + Show More + + ), + false: undefined + }), + expandableSectionContent: figma.boolean('Expandable', { + true: ( + + Expandable content + + ), + false: undefined + }) + }, + example: (props) => ( + + + {props.editorText} + {props.expandableSectionContent} + + {props.expandableSectionToggle} + + ) + } +); diff --git a/packages/code-connect/components/CodeEditor/CodeEditor.figma.tsx b/packages/code-connect/components/CodeEditor/CodeEditor.figma.tsx new file mode 100644 index 00000000000..640c9412d02 --- /dev/null +++ b/packages/code-connect/components/CodeEditor/CodeEditor.figma.tsx @@ -0,0 +1,42 @@ +import figma from '@figma/code-connect'; +import { CodeEditor } from '@patternfly/react-code-editor'; + +// TODO: DESIGN: Add support for actions, wrap each action in the appropriate compnent +// TODO: DESIGN: When shortcuts is removed, presentation breaks +// TODO: DESIGN: configure options for actions +// TODO: DESIGN: Add viewshortcuts +// TODO: DESIGN: ifshortcuts is true +// Documentation for CodeEditor can be found at https://www.patternfly.org/components/code-editor + +figma.connect( + CodeEditor, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=16994-184502', + { + props: { + // boolean + hasCustomControls: '', + isUploadEnabled: figma.boolean('Action 1'), + isCopyEnabled: figma.boolean('Action 2'), + isDownloadEnabled: figma.boolean('Action 3'), + showsLineNumbers: figma.boolean('Show Line Numbers'), + + // enum + isMinimapVisible: figma.enum('Type', { 'Mini Map': true }) + }, + example: (props) => ( + <> + + + ) + } +); diff --git a/packages/code-connect/components/DataList/DataList.figma.tsx b/packages/code-connect/components/DataList/DataList.figma.tsx new file mode 100644 index 00000000000..cceb9c61217 --- /dev/null +++ b/packages/code-connect/components/DataList/DataList.figma.tsx @@ -0,0 +1,23 @@ +import figma from '@figma/code-connect'; +import { DataList } from '@patternfly/react-core'; + +// TODO: DESIGN: Separate examples, rename files to match their react counterparts. +// Documentation for DataList can be found at https://www.patternfly.org/components/data-list + +figma.connect( + DataList, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=6649-80542', + { + props: { + // enum + isCompact: figma.enum('Size', { Compact: true }), + + children: figma.children('*') + }, + example: (props) => ( + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/DataList/_1BuildItYourselfBasicRows.figma.tsx b/packages/code-connect/components/DataList/_1BuildItYourselfBasicRows.figma.tsx new file mode 100644 index 00000000000..6c8d4ecfe33 --- /dev/null +++ b/packages/code-connect/components/DataList/_1BuildItYourselfBasicRows.figma.tsx @@ -0,0 +1,18 @@ +import figma from '@figma/code-connect'; +import { DataListItem, DataListItemRow } from '@patternfly/react-core'; + +figma.connect( + DataListItemRow, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=6649-69488&m=dev', + { + props: { + children: figma.children('*') + }, + example: (props) => ( + // aria-labelledby should point to an ID within the DataListItemRow/DataListItemCell + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/DataList/_1BuildItYourselfClickableRows.figma.tsx b/packages/code-connect/components/DataList/_1BuildItYourselfClickableRows.figma.tsx new file mode 100644 index 00000000000..f06513ba576 --- /dev/null +++ b/packages/code-connect/components/DataList/_1BuildItYourselfClickableRows.figma.tsx @@ -0,0 +1,20 @@ +import figma from '@figma/code-connect'; +import { DataListItem, DataListItemRow } from '@patternfly/react-core'; + +// Documentation for DataListItemRow can be found at https://www.patternfly.org/components/data-list + +figma.connect( + DataListItemRow, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=6649-96947', + { + props: { + children: figma.children('*') + }, + example: (props) => ( + // aria-labelledby should point to an ID within the DataListItemRow/DataListItemCell + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/DataList/_1BuildItYourselfDraggableRows.figma.tsx b/packages/code-connect/components/DataList/_1BuildItYourselfDraggableRows.figma.tsx new file mode 100644 index 00000000000..f1c90db7194 --- /dev/null +++ b/packages/code-connect/components/DataList/_1BuildItYourselfDraggableRows.figma.tsx @@ -0,0 +1,26 @@ +import figma from '@figma/code-connect'; +import { DataList } from '@patternfly/react-core'; + +// Documentation for DataListItemRow can be found at https://www.patternfly.org/components/data-list +// This variant has been refactored to use the DragDropSort component. +// In order to use this variant, you must wrap the DataList component in a DragDropSort component. + +figma.connect( + DataList, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=19618-55289', + { + example: () => + 'Draggable DataList variant has been refactored to use the DragDropSort component. The design is the same, but the implementation is different. This component variant requires refactoring to work within the new context. For more information, see the example at https://www.patternfly.org/components/data-list/#draggable.' + // Code example: + // { + // setItems(newItems); + // }} + // variant="DataList" + // overlayProps={{ isCompact: true }} + // > + // + // + } +); diff --git a/packages/code-connect/components/DataList/_2BaseComponentsActionCell.figma.tsx b/packages/code-connect/components/DataList/_2BaseComponentsActionCell.figma.tsx new file mode 100644 index 00000000000..75c18d6e8bf --- /dev/null +++ b/packages/code-connect/components/DataList/_2BaseComponentsActionCell.figma.tsx @@ -0,0 +1,16 @@ +import figma from '@figma/code-connect'; +import { DataListAction } from '@patternfly/react-core'; + +// Documentation for DataListItemRow can be found at https://www.patternfly.org/components/data-list + +figma.connect( + DataListAction, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=6596-33965', + { + example: () => ( + + 'Action' + + ) + } +); diff --git a/packages/code-connect/components/DataList/_2BaseComponentsContentCell.figma.tsx b/packages/code-connect/components/DataList/_2BaseComponentsContentCell.figma.tsx new file mode 100644 index 00000000000..a7d4356a90e --- /dev/null +++ b/packages/code-connect/components/DataList/_2BaseComponentsContentCell.figma.tsx @@ -0,0 +1,44 @@ +import figma from '@figma/code-connect'; +import { Icon, DataListCell, DataListItem, DataListItemCells, DataListItemRow } from '@patternfly/react-core'; + +// TODO: DESIGN: Either name layers uniquely or create a dataListCell component to house +// Documentation for DataList can be found at https://www.patternfly.org/components/data-list + +figma.connect( + DataListCell, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=6596-33934', + { + props: { + showDescriptionText: figma.boolean('Show description text'), + + // enum + isIcon: figma.enum('Type', { + 'Filled - Plain text': true + }), + isFilled: figma.enum('Type', { + 'Filled - Plain text': true, + 'Filled - Link text': true + }), + + primaryContent: 'Main content', + secondaryContent: 'Second content block' + }, + example: (props) => ( + + + + + , + + {props.primaryContent} + , + {props.secondaryContent} + ]} + /> + + + ) + } +); diff --git a/packages/code-connect/components/DataList/_2BaseComponentsControlCell.figma.tsx b/packages/code-connect/components/DataList/_2BaseComponentsControlCell.figma.tsx new file mode 100644 index 00000000000..c709bd6ed9f --- /dev/null +++ b/packages/code-connect/components/DataList/_2BaseComponentsControlCell.figma.tsx @@ -0,0 +1,49 @@ +import figma from '@figma/code-connect'; +import { + // DataListAction, + DataListCheck, + DataListControl, + DataListToggle +} from '@patternfly/react-core'; + +// TODO: 2. Base Components/Control cell - These cells need unique names. Either create components for DataListCell, +// DataListToggle, DataListDragButton, DataListAction, DataListCheck +// These component specifics are unreachable unless separated into their own entities +// Documentation for DataListControl can be found at https://www.patternfly.org/components/data-list + +// const selectableCell = { +// +// return ( +// <> +// {props.isSelectable} +// {props.isExpandable} +// {props.isDraggable} +// +// {props.children} +// +// +// ); +// }; + +figma.connect( + DataListControl, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=6596-34013', + { + props: { + isExpandable: figma.boolean('Row expansion', { + true: {}} isExpanded={false} id="toggle1" aria-controls="expand1" />, + false: undefined + }), + isSelectable: figma.boolean('Row select', { + true: , + false: undefined + }) + }, + example: (props) => ( + <> + {props.isSelectable} + {props.isExpandable} + + ) + } +); diff --git a/packages/code-connect/components/DatePicker/BaseComponentsCalendarDay.figma.tsx b/packages/code-connect/components/DatePicker/BaseComponentsCalendarDay.figma.tsx new file mode 100644 index 00000000000..8fde324c68f --- /dev/null +++ b/packages/code-connect/components/DatePicker/BaseComponentsCalendarDay.figma.tsx @@ -0,0 +1,15 @@ +import figma from '@figma/code-connect'; +import { CalendarMonth } from '@patternfly/react-core'; + +// Documentation for CalendarMonth can be found at https://www.patternfly.org/components/calendar-month + +figma.connect( + CalendarMonth, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7741-2677', + { + props: { + date: '2025-06-16' + }, + example: (props) => {}} onMonthChange={() => {}} /> + } +); diff --git a/packages/code-connect/components/DatePicker/CalendarMonth.figma.tsx b/packages/code-connect/components/DatePicker/CalendarMonth.figma.tsx new file mode 100644 index 00000000000..0f226f5a427 --- /dev/null +++ b/packages/code-connect/components/DatePicker/CalendarMonth.figma.tsx @@ -0,0 +1,51 @@ +import figma from '@figma/code-connect'; +import { CalendarMonth, Title } from '@patternfly/react-core'; + +// Documentation for CalendarMonth can be found at https://www.patternfly.org/components/calendar-month +const sharedProps = { + inlineProps: { + component: 'article', + title: ( + + Select your favorite date + + ) + } +}; + +figma.connect( + CalendarMonth, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136846', + { + props: { + ...sharedProps, + date: '2025-06-16' + }, + example: (props) => ( + {}} onMonthChange={() => {}} /> + ) + } +); + +figma.connect( + CalendarMonth, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136846', + { + props: { + ...sharedProps, + variant: { Type: 'With date range' }, + startDate: new Date(2020, 10, 11), + endDate: new Date(2020, 10, 24) + }, + example: (props) => ( + {}} + onMonthChange={() => {}} + rangeStart={props.startDate} + /> + ) + } +); diff --git a/packages/code-connect/components/DatePicker/DateAndTimePicker.figma.tsx b/packages/code-connect/components/DatePicker/DateAndTimePicker.figma.tsx new file mode 100644 index 00000000000..8d7366ab344 --- /dev/null +++ b/packages/code-connect/components/DatePicker/DateAndTimePicker.figma.tsx @@ -0,0 +1,94 @@ +import figma from '@figma/code-connect'; +import { + Button, + CalendarMonth, + Dropdown, + DropdownItem, + DropdownList, + InputGroup, + InputGroupItem, + MenuToggle, + Popover, + TextInput, + TimePicker +} from '@patternfly/react-core'; +import OutlinedCalendarAltIcon from '@patternfly/react-icons/dist/esm/icons/outlined-calendar-alt-icon'; +import OutlinedClockIcon from '@patternfly/react-icons/dist/esm/icons/outlined-clock-icon'; + +// Documentation for TimePicker can be found at https://www.patternfly.org/components/time-picker + +const sharedProps = { + time: ( + {}} + isOpen={false} + onOpenChange={() => {}} + toggle={(toggleRef) => ( + {}} + isExpanded={false} + aria-label="Time picker" + icon={} + /> + )} + > + + + Action + + + Operation + + + + ), + calendarButton: ( + + + + + + ) + } +); + +figma.connect( + DescriptionListTerm, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=36279-2532', + { + variant: { 'Has help text': true, 'Inline edit toggle': false }, + props: { + // string + label: figma.string('✏️ Label'), + + // enum + icon: figma.enum('Icon ⎆', { + true: , + false: undefined + }) + }, + example: (props) => ( + + {props.label}} bodyContent={
This is the help text
}> + + {props.icon} + {props.label} + +
+
+ ) + } +); + +figma.connect( + DescriptionListTerm, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=36279-2532', + { + props: { + // string + label: figma.string('✏️ Label'), + + // enum + icon: figma.enum('Icon ⎆', { + true: , + false: undefined + }) + }, + example: (props) => {props.label} + } +); diff --git a/packages/code-connect/components/Divider/Divider.figma.tsx b/packages/code-connect/components/Divider/Divider.figma.tsx new file mode 100644 index 00000000000..18189ce4f65 --- /dev/null +++ b/packages/code-connect/components/Divider/Divider.figma.tsx @@ -0,0 +1,61 @@ +import figma from '@figma/code-connect'; +import { Divider, Flex, FlexItem } from '@patternfly/react-core'; + +// Documentation for Divider can be found at https://www.patternfly.org/components/divider + +figma.connect( + Divider, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=2764-6708', + { + props: { + // TODO: Figma allows optional insets, but default to insetMd + inset: figma.boolean('With insets', { + true: { default: 'insetMd' }, + false: { default: 'insetNone' } + }), + // TODO: This is a good example of how properties in Figma and props in React would benefit from naming consistency + // React is looking for orientation, figma is defining orientation as 'Direction' + orientation: figma.enum('Direction', { + Horizontal: { default: undefined }, + Vertical: { default: 'vertical' } + }) + }, + example: (props) => ( + + first item + + + ) + } +); + +figma.connect( + Divider, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6%3A-Components-Test?node-id=2764-6708', + { + props: { + // TODO: Figma allows optional insets, but default to insetMd + inset: figma.boolean('With insets', { + true: { default: 'insetMd' }, + false: { default: 'insetNone' } + }), + // TODO: This is a good example of how properties in Figma and props in React would benefit from naming consistency + // React is looking for orientation, figma is defining orientation as 'Direction' + orientation: figma.enum('Direction', { + Horizontal: { default: undefined }, + Vertical: { default: 'vertical' } + }) + }, + example: (props) => ( + + ) + } +); diff --git a/packages/code-connect/components/Drawer/Drawer.figma.tsx b/packages/code-connect/components/Drawer/Drawer.figma.tsx new file mode 100644 index 00000000000..d2b54f2ed8a --- /dev/null +++ b/packages/code-connect/components/Drawer/Drawer.figma.tsx @@ -0,0 +1,74 @@ +import figma from '@figma/code-connect'; +import { + Drawer, + DrawerActions, + DrawerCloseButton, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerPanelBody, + DrawerPanelContent, + DrawerPanelDescription +} from '@patternfly/react-core'; + +// TODO: DESIGN: Drawer is not using base components, rather it's using layers. Layers should be replaced with base components. +// Panel content is currently static. Once updated to components, it will be updated to be dynamic. +// Documentation for Drawer can be found at https://www.patternfly.org/components/drawer + +figma.connect( + Drawer, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=8034-7676', + { + props: { + // boolean + isExpanded: true, + colorVariant: figma.enum('Background', { + Secondary: 'secondary', + Primary: undefined + }), + + // enum + isInline: figma.enum('Type', { Inline: true }), + position: figma.enum('Position', { + 'Left In Main Content Area': 'start', + 'Right - Full Page': undefined, + 'Left - Full Page': 'start', + 'Right Full Page': undefined, + 'Bottom Full Page': 'bottom', + 'Bottom In Main Content Area': 'bottom', + 'Right In Main Content Area': undefined + }) + + // Once updatedted to use child components, this will be used to render content. + // panelContent: figma.children(['Drawer Header', 'Drawer Tabs', 'Drawer Content']) + }, + example: (props) => ( + {}} + > + + + Drawer panel header + + {}} /> + + + Drawer panel description + Drawer panel body + + } + > + Drawer body content + + + ) + } +); diff --git a/packages/code-connect/components/Drawer/DrawerContent.figma.tsx b/packages/code-connect/components/Drawer/DrawerContent.figma.tsx new file mode 100644 index 00000000000..c9fe8b29897 --- /dev/null +++ b/packages/code-connect/components/Drawer/DrawerContent.figma.tsx @@ -0,0 +1,15 @@ +import figma from '@figma/code-connect'; +import { DrawerContent } from '@patternfly/react-core'; + +// Documentation for DrawerContent can be found at https://www.patternfly.org/components/drawer + +figma.connect( + DrawerContent, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=35627-47890', + { + props: { + panelContent: figma.children('*') + }, + example: (props) => + } +); diff --git a/packages/code-connect/components/DualListSelector/DualListHeader.figma.tsx b/packages/code-connect/components/DualListSelector/DualListHeader.figma.tsx new file mode 100644 index 00000000000..e53668ef174 --- /dev/null +++ b/packages/code-connect/components/DualListSelector/DualListHeader.figma.tsx @@ -0,0 +1,65 @@ +import figma from '@figma/code-connect'; +import { Button, ButtonVariant, DualListSelectorPane, SearchInput } from '@patternfly/react-core'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; + +// Documentation for DualListHeader can be found at https://www.patternfly.org/components/dual-list-selector + +figma.connect( + DualListSelectorPane, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=21279-116172', + { + props: { + icon: , // placeholder icon + + // string + itemInformation: figma.string('Item information'), + title: figma.string('Header text'), + + // boolean + onSearch: figma.boolean('Has search bar', { + true: () => {}, + false: undefined + }), + isSearchable: figma.boolean('Has search bar', { + true: ( + {}} onClear={() => {}} aria-label={paneSearchLabel} /> + ), + false: undefined + }), + actions: figma.boolean('Has search bar', { + true: [ + + + + + + + + + + + + + + ) + } +); diff --git a/packages/code-connect/components/FileUpload/MultipleFileUpload.figma.tsx b/packages/code-connect/components/FileUpload/MultipleFileUpload.figma.tsx new file mode 100644 index 00000000000..d57533f9693 --- /dev/null +++ b/packages/code-connect/components/FileUpload/MultipleFileUpload.figma.tsx @@ -0,0 +1,70 @@ +import figma from '@figma/code-connect'; +import { + FileUpload, + MultipleFileUpload, + MultipleFileUploadMain, + MultipleFileUploadStatus, + MultipleFileUploadStatusItem +} from '@patternfly/react-core'; +import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; + +// TODO: DESIGN: Add status toggle text +// TODO: DESIGN: Add status toggle icon +// TODO: DESIGN: Add text separator +// TODO: DESIGN: Add info text +// TODO: DESIGN: Add status toggle text +// TODO: DESIGN: Add status toggle icon + +figma.connect( + FileUpload, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=8949-96128', + { + props: { + // static + titleText: 'Drag and drop files here', + titleTextSeparator: 'or', + infoText: 'Accepted file types: JPEG, Doc, PDF, PNG', + + // enum + isHorizontal: figma.enum('Layout', { Horizontal: true }), + + children: figma.children('*') + }, + example: (props) => ( + // Documentation for FileUpload can be found at https://www.patternfly.org/components/file-upload + {}} + > + } + titleText={props.titleText} + titleTextSeparator={props.titleTextSeparator} + /> + + + {}} + onReadSuccess={() => {}} + onReadFail={() => {}} + /> + + + ) + } +); diff --git a/packages/code-connect/components/FileUpload/SimpleFileUpload.figma.tsx b/packages/code-connect/components/FileUpload/SimpleFileUpload.figma.tsx new file mode 100644 index 00000000000..f64e56b0379 --- /dev/null +++ b/packages/code-connect/components/FileUpload/SimpleFileUpload.figma.tsx @@ -0,0 +1,61 @@ +import figma from '@figma/code-connect'; +import { FileUpload, FileUploadHelperText, HelperText, HelperTextItem } from '@patternfly/react-core'; + +// TODO: DESIGN: Add filename placeholder +// TODO: DESIGN: Add browse button text +// TODO: DESIGN: Add FileUploadHelperText + +figma.connect( + FileUpload, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=8949-96043', + { + props: { + // boolean + showHelperText: figma.boolean('Show helper text'), + hideDefaultPreview: figma.boolean('Show text preview box', { + true: false, + false: true + }), + helperText: figma.boolean('Show helper text', { + true: ( + + + Upload a CSV file + + + ), + false: undefined + }), + + // enum + allowEditingUploadedText: figma.enum('State', { 'Uploaded + Editable': true }), + isLoading: figma.enum('State', { 'In progress upload': true }), + isValidated: figma.enum('State', { + 'Invalid upload': 'error', + 'Uploaded + Editable': 'success', + 'Uploaded + Not Editable': 'success' + }) + }, + example: (props) => ( + // Documentation for FileUpload can be found at https://www.patternfly.org/components/file-upload + {}} + onDataChange={() => {}} + onTextChange={() => {}} + onReadStarted={() => {}} + onReadFinished={() => {}} + onClearClick={() => {}} + > + {props.helperText} + + ) + } +); diff --git a/packages/code-connect/components/Hint/Hint.figma.tsx b/packages/code-connect/components/Hint/Hint.figma.tsx new file mode 100644 index 00000000000..99116bb3c58 --- /dev/null +++ b/packages/code-connect/components/Hint/Hint.figma.tsx @@ -0,0 +1,95 @@ +import figma from '@figma/code-connect'; +import { + Hint, + HintBody, + HintFooter, + HintTitle, + DropdownList, + Dropdown, + DropdownItem, + Divider +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; +import MenuToggle from '@patternfly/react-core/dist/js/components/MenuToggle/MenuToggle'; + +// TODO: DESIGN: Use dropdown from figma for actions +// TODO: DESIGN: Create hint title +// TODO: DESIGN: Create hint body +// TODO: DESIGN: Create hint footer + +// Note: Figma will not render conditional props within React components. +// This means that the , , and tags will not be properly render figma.string() +// Documentation for Hint can be found at https://www.patternfly.org/components/hint + +figma.connect( + Hint, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1118-3329', + { + props: { + // Pre-defined title options (enum works, boolean with JSX doesn't) + hintTitle: figma.enum('Show Title', { + false: undefined, + true: Hint title + }), + + // Pre-defined body options + hintBody: figma.enum('Show Body', { + false: undefined, + true: This is hint body text that provides helpful information. + }), + + // Pre-defined footer options + hintFooter: figma.enum('Show Footer', { + false: undefined, + true: Footer content or link + }) + }, + example: (props) => ( + {}} + onOpenChange={() => {}} + toggle={(toggleRef) => ( + {}} + isExpanded={false} + icon={} + /> + )} + > + + + Action + + {}}> + Link + + + Disabled Action + + + Disabled Link + + + + Separated Action + + {}}> + Separated Link + + + + } + > + {props.hintTitle} + {props.hintBody} + {props.hintFooter} + + ) + } +); diff --git a/packages/code-connect/components/InlineEdit/FieldSpecificInlineEdit.figma.tsx b/packages/code-connect/components/InlineEdit/FieldSpecificInlineEdit.figma.tsx new file mode 100644 index 00000000000..38ec11644d0 --- /dev/null +++ b/packages/code-connect/components/InlineEdit/FieldSpecificInlineEdit.figma.tsx @@ -0,0 +1,53 @@ +import figma from '@figma/code-connect'; + +// Inline edit is NOT a React component +// Documentation for InlineEdit can be found at https://www.patternfly.org/components/inline-edit + +figma.connect('https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1664-8856', { + props: {}, + example: () => ( +
+
+
+ Static value +
+
+ +
+
+
+
+ + + +
+
+
+ +
+
+ +
+
+
+
+ ) +}); diff --git a/packages/code-connect/components/InlineEdit/InlineEditActionGroup.figma.tsx b/packages/code-connect/components/InlineEdit/InlineEditActionGroup.figma.tsx new file mode 100644 index 00000000000..0837009b006 --- /dev/null +++ b/packages/code-connect/components/InlineEdit/InlineEditActionGroup.figma.tsx @@ -0,0 +1,24 @@ +import figma from '@figma/code-connect'; + +// Inline edit is NOT a React component +// Documentation for InlineEdit can be found at https://www.patternfly.org/components/inline-edit + +figma.connect('https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1664-5805', { + props: {}, + example: () => ( +
+
+
+ +
+
+ +
+
+
+ ) +}); diff --git a/packages/code-connect/components/InlineEdit/InlineEditToggle.figma.tsx b/packages/code-connect/components/InlineEdit/InlineEditToggle.figma.tsx new file mode 100644 index 00000000000..d20bca9228b --- /dev/null +++ b/packages/code-connect/components/InlineEdit/InlineEditToggle.figma.tsx @@ -0,0 +1,25 @@ +import figma from '@figma/code-connect'; + +// Inline edit is NOT a React component +// Documentation for InlineEdit can be found at https://www.patternfly.org/components/inline-edit + +figma.connect('https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1664-8905', { + props: {}, + example: () => ( +
+
+ +
+
+ ) +}); diff --git a/packages/code-connect/components/JumpLinks/JumplinkHorizontal.figma.tsx b/packages/code-connect/components/JumpLinks/JumplinkHorizontal.figma.tsx new file mode 100644 index 00000000000..00be3d4f189 --- /dev/null +++ b/packages/code-connect/components/JumpLinks/JumplinkHorizontal.figma.tsx @@ -0,0 +1,24 @@ +import figma from '@figma/code-connect'; +import { JumpLinksItem } from '@patternfly/react-core'; + +// TODO: DESIGN: FIGMA: Remove icons, help popup, and close button +// Documentation for JumpLinks can be found at https://www.patternfly.org/components/jump-links + +figma.connect( + JumpLinksItem, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=5286-5330', + { + props: { + // string + tabText: figma.string('Tab Text'), + + // enum + isActive: figma.enum('State', { Selected: true }) + }, + example: (props) => ( + + {props.tabText} + + ) + } +); diff --git a/packages/code-connect/components/JumpLinks/JumplinkVertical.figma.tsx b/packages/code-connect/components/JumpLinks/JumplinkVertical.figma.tsx new file mode 100644 index 00000000000..927a4e897a4 --- /dev/null +++ b/packages/code-connect/components/JumpLinks/JumplinkVertical.figma.tsx @@ -0,0 +1,23 @@ +import figma from '@figma/code-connect'; +import { JumpLinksItem } from '@patternfly/react-core'; + +// Documentation for JumpLinks can be found at https://www.patternfly.org/components/jump-links + +figma.connect( + JumpLinksItem, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=5426-8306', + { + props: { + // string + tabText: figma.string('Tab Text'), + + // enum + isActive: figma.enum('State', { Selected: true }) + }, + example: (props) => ( + + {props.tabText} + + ) + } +); diff --git a/packages/code-connect/components/JumpLinks/JumplinksHorizontal.figma.tsx b/packages/code-connect/components/JumpLinks/JumplinksHorizontal.figma.tsx new file mode 100644 index 00000000000..10ba1868643 --- /dev/null +++ b/packages/code-connect/components/JumpLinks/JumplinksHorizontal.figma.tsx @@ -0,0 +1,25 @@ +import figma from '@figma/code-connect'; +import { JumpLinks } from '@patternfly/react-core'; + +// Documentation for JumpLinks can be found at https://www.patternfly.org/components/jump-links + +figma.connect( + JumpLinks, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=8644-150823', + { + props: { + // boolean + label: figma.boolean('Show label', { + true: 'Jump to section', + false: undefined + }), + + children: figma.children('*') + }, + example: (props) => ( + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/JumpLinks/JumplinksVertical.figma.tsx b/packages/code-connect/components/JumpLinks/JumplinksVertical.figma.tsx new file mode 100644 index 00000000000..e0d18ce0d57 --- /dev/null +++ b/packages/code-connect/components/JumpLinks/JumplinksVertical.figma.tsx @@ -0,0 +1,25 @@ +import figma from '@figma/code-connect'; +import { JumpLinks } from '@patternfly/react-core'; + +// Documentation for JumpLinks can be found at https://www.patternfly.org/components/jump-links + +figma.connect( + JumpLinks, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=5426-8542', + { + props: { + // boolean + label: figma.boolean('Show Label', { + true: 'Jump to section', + false: undefined + }), + + children: figma.children('*') + }, + example: (props) => ( + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/Label/LabelGroups.figma.tsx b/packages/code-connect/components/Label/LabelGroups.figma.tsx new file mode 100644 index 00000000000..d71b4f69849 --- /dev/null +++ b/packages/code-connect/components/Label/LabelGroups.figma.tsx @@ -0,0 +1,230 @@ +import figma from '@figma/code-connect'; +import { Label, LabelGroup } from '@patternfly/react-core'; + +// Documentation for LabelGroups can be found at https://www.patternfly.org/components/label + +const sharedProps = { + closableLabels: ( + <> + + + + + + + + + + + ), + editableLabels: ( + <> + + + + + + + + + + + ) +}; + +figma.connect( + LabelGroup, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=2800-1075', + { + props: { + ...sharedProps, + // boolean + numLabels: figma.boolean('Has collapsed labels', { + true: 6, + false: undefined + }), + + // enum + addLabelControl: figma.enum('Type', { + 'Label management': ( + + ) + }) + }, + example: (props) => ( + {}} + > + {props.closableLabels} + + ) + } +); + +figma.connect( + LabelGroup, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=2800-1075', + { + variant: { Type: 'Label management' }, + props: { + ...sharedProps, + // boolean + numLabels: figma.boolean('Has collapsed labels', { + true: 6, + false: undefined + }), + + // enum + addLabelControl: figma.enum('Type', { + 'Label management': ( + + ) + }) + }, + example: (props) => ( + {}} + > + {props.editableLabels} + + ) + } +); diff --git a/packages/code-connect/components/Label/LabelInGroup.figma.tsx b/packages/code-connect/components/Label/LabelInGroup.figma.tsx new file mode 100644 index 00000000000..561c66ec342 --- /dev/null +++ b/packages/code-connect/components/Label/LabelInGroup.figma.tsx @@ -0,0 +1,28 @@ +import figma from '@figma/code-connect'; +import { Badge, Label } from '@patternfly/react-core'; + +// TODO: DESIGN: Reconfigure how numlabels is set. Currently, the text string "more" is not customizable +// TODO: DESIGN: Label group should contain label components + +// NOTE: "Label overflow" doesn't appear to be necessary +// Documentation for Label can be found at https://www.patternfly.org/components/label-group + +figma.connect(Label, 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=2800-1067', { + props: { + labelText: figma.string('Label text'), + isCloseable: figma.boolean('Has Close button', { + true: `{() => {}}`, + false: undefined + }), + badge: figma.boolean('Has counter', { + true: 06, + false: undefined + }) + }, + example: (props) => ( + + ) +}); diff --git a/packages/code-connect/components/Label/LabelNonStatus.figma.tsx b/packages/code-connect/components/Label/LabelNonStatus.figma.tsx new file mode 100644 index 00000000000..466f51b8c49 --- /dev/null +++ b/packages/code-connect/components/Label/LabelNonStatus.figma.tsx @@ -0,0 +1,57 @@ +import figma from '@figma/code-connect'; +import { Label } from '@patternfly/react-core'; + +// Documentation for Label can be found at https://www.patternfly.org/components/label +// TODO: DESIGN: Update status to be a prop + +figma.connect( + Label, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2800-609', + { + props: { + status: 'info', // TODO: DESIGN: Update status to be a prop + // string + labelText: figma.string('Text'), + + // boolean + isEditable: figma.boolean('Is Editable', { + true: { + isEditable: true, + onEditCancel: () => {}, // Callback when an editable label cancels an edit. + onEditComplete: () => {}, // Callback when an editable label completes an edit. + editableProps: { + 'aria-label': `Editable label with text`, + id: 'editable-label' + } + }, + false: undefined + }), + + // enum + isCompact: figma.enum('Size', { Compact: true }), + color: figma.enum('Color', { + Red: 'red', + Orange: 'orange', + 'Orange Red': 'orangered', + Green: 'green', + Blue: 'blue', + Purple: 'purple', + Grey: 'grey', + Cyan: 'teal', // TODO: DESIGN: Update to teal + Gold: 'yellow' // TODO: DESIGN: Update to yellow + }), + variant: figma.enum('Type', { Outlined: 'outline' }) + }, + example: (props) => ( + + ) + } +); diff --git a/packages/code-connect/components/Label/LabelStatus.figma.tsx b/packages/code-connect/components/Label/LabelStatus.figma.tsx new file mode 100644 index 00000000000..e8cb48a55d5 --- /dev/null +++ b/packages/code-connect/components/Label/LabelStatus.figma.tsx @@ -0,0 +1,31 @@ +import figma from '@figma/code-connect'; +import { Label } from '@patternfly/react-core'; + +// Documentation for Label can be found at https://www.patternfly.org/components/label + +figma.connect( + Label, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2800-488', + { + props: { + // string + text: figma.string('Text'), + isCompact: figma.enum('Size', { Compact: true }), + + // enum + variant: figma.enum('Type', { Outlined: 'outline' }), + status: figma.enum('Status', { + Success: 'success', + Warning: 'warning', + Danger: 'danger', + Info: 'info', + Custom: 'custom' + }) + }, + example: (props) => ( + + ) + } +); diff --git a/packages/code-connect/components/LoginPage/DesktopLoginPage.figma.tsx b/packages/code-connect/components/LoginPage/DesktopLoginPage.figma.tsx new file mode 100644 index 00000000000..b1849790164 --- /dev/null +++ b/packages/code-connect/components/LoginPage/DesktopLoginPage.figma.tsx @@ -0,0 +1,32 @@ +import figma from '@figma/code-connect'; +import { LoginPage } from '@patternfly/react-core'; + +// TODO: Map Figma component to these properties +// Documentation for LoginPage can be found at https://www.patternfly.org/components/login-page + +figma.connect( + LoginPage, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2104-4180', + { + props: { + children: figma.children('*') + }, + example: (props) => ( + + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/Masthead/Masthead.figma.tsx b/packages/code-connect/components/Masthead/Masthead.figma.tsx new file mode 100644 index 00000000000..56982963c5b --- /dev/null +++ b/packages/code-connect/components/Masthead/Masthead.figma.tsx @@ -0,0 +1,105 @@ +import figma from '@figma/code-connect'; +import { + Button, + Masthead, + MastheadContent, + MastheadMain, + MastheadToggle, + Menu, + MenuSearch, + MenuSearchInput, + SearchInput, + Divider, + MenuContent, + MenuList, + MenuItem, + Nav, + NavItem, + NavList +} from '@patternfly/react-core'; +import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon'; +import { useState } from 'react'; + +// TODO: DESIGN: Create masthead main section MastheadMain MastheadContent +// TODO: DESIGN: Move Context Switcher, Horizontal Nav, etc to MastheadContent +// TODO: DESIGN: Create necessary wrappers for MastheadToggle, MastheadBrand, MastheadContent +// Documentation for Masthead can be found at https://www.patternfly.org/components/masthead + +const sharedProps = { + mastheadContent: figma.enum('Masthead content', { + 'Context switcher': ( + {}} activeItemId={0}> + + + {}} /> + + + + + + Item 1 + Item 2 + Item 3 + + + + ), + 'Horizontal navigation': ( + + ) + }) +}; + +figma.connect( + Masthead, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2104-6642', + { + props: { + ...sharedProps, + mastheadBrand: figma.children('Masthead logo'), + mastheadToggle: figma.boolean('Left Menu Toggle', { + true: ( + + + { + setIsOpen(!isOpen); + }} + variant={props.variant} + > + + + {props.modalContent} + + {props.modalFooter} + + + + ); + } + } +); diff --git a/packages/code-connect/components/Modal/BasicModal.figma.tsx b/packages/code-connect/components/Modal/BasicModal.figma.tsx new file mode 100644 index 00000000000..ccfcd4e40b2 --- /dev/null +++ b/packages/code-connect/components/Modal/BasicModal.figma.tsx @@ -0,0 +1,84 @@ +import figma from '@figma/code-connect'; +import { Button, Modal, ModalBody, ModalFooter, ModalHeader, Popover } from '@patternfly/react-core'; +import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; + +// TODO: DESIGN: Add Modal Body component to Modal +// TODO: DESIGN: Add Modal Footer component to Modal +// TODO: DESIGN: Add Modal Header component to Modal +// Documentation for Modal can be found at https://www.patternfly.org/components/modal + +figma.connect( + Modal, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=2937-158', + { + props: { + // boolean + hasDescription: figma.boolean('Description', { + true: 'Product description goes here', + false: undefined + }), + help: figma.boolean('Help icon', { + true: ( + Help Popover} + bodyContent={ +
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis. +
+ } + footerContent="Popover Footer" + > + + setIsOpen(!isModalOpen)} // handles the close button + variant={props.variant} + > + + {props.modalContent} + {props.modalFooter} + + + + ); + } + } +); diff --git a/packages/code-connect/components/NotificationDrawer/NotificationDrawer.figma.tsx b/packages/code-connect/components/NotificationDrawer/NotificationDrawer.figma.tsx new file mode 100644 index 00000000000..c690f7a14fd --- /dev/null +++ b/packages/code-connect/components/NotificationDrawer/NotificationDrawer.figma.tsx @@ -0,0 +1,54 @@ +import figma from '@figma/code-connect'; +import { + NotificationDrawer, + NotificationDrawerBody, + NotificationDrawerGroupList, + NotificationDrawerList +} from '@patternfly/react-core'; + +// Documentation for NotificationDrawer can be found at https://www.patternfly.org/components/notification-drawer + +// Default +figma.connect( + NotificationDrawer, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=7172-99015', + { + props: { + // children + notificationDrawerHeader: figma.children('Notification drawer header'), + notificationDrawerItems: figma.children(['Notifications', 'Notification drawer item']) + }, + example: (props) => ( + // Documentation for NotificationDrawer can be found at https://www.patternfly.org/components/notification-drawer + + {props.notificationDrawerHeader} + + {props.notificationDrawerItems} + + + ) + } +); + +// Grouped +figma.connect( + NotificationDrawer, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=7172-99015', + { + variant: { Type: 'Grouped' }, + props: { + // children + notificationDrawerHeader: figma.children('Notification drawer header'), + notificationDrawerGroup: figma.children('Notification drawer groups') + }, + example: (props) => ( + // Documentation for NotificationDrawer can be found at https://www.patternfly.org/components/notification-drawer + + {props.notificationDrawerHeader} + + {props.notificationDrawerGroup} + + + ) + } +); diff --git a/packages/code-connect/components/NotificationDrawer/NotificationDrawerGroups.figma.tsx b/packages/code-connect/components/NotificationDrawer/NotificationDrawerGroups.figma.tsx new file mode 100644 index 00000000000..57b467b0f8f --- /dev/null +++ b/packages/code-connect/components/NotificationDrawer/NotificationDrawerGroups.figma.tsx @@ -0,0 +1,42 @@ +import figma from '@figma/code-connect'; +import { NotificationDrawerGroup, NotificationDrawerList } from '@patternfly/react-core'; + +// TODO: DESIGN: Split unread count into a separate prop + +figma.connect( + NotificationDrawerGroup, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=3172-18190', + { + props: { + // string + headingText: figma.string('Group title'), + count: 3, + + // boolean + badgeProps: figma.boolean('Has count', { + true: figma.nestedProps('Badge', { + count: figma.string('Text') + }), + false: { count: undefined } + }), + + // enum + isExpanded: figma.enum('Type', { + Collapsed: false, + Expanded: true + }), + + children: figma.children('Notification drawer item') + }, + example: (props) => ( + {}} + > + {props.children} + + ) + } +); diff --git a/packages/code-connect/components/NotificationDrawer/NotificationDrawerHeader.figma.tsx b/packages/code-connect/components/NotificationDrawer/NotificationDrawerHeader.figma.tsx new file mode 100644 index 00000000000..c11b30a9937 --- /dev/null +++ b/packages/code-connect/components/NotificationDrawer/NotificationDrawerHeader.figma.tsx @@ -0,0 +1,62 @@ +import figma from '@figma/code-connect'; +import { Dropdown, DropdownItem, DropdownList, MenuToggle, NotificationDrawerHeader } from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons//ellipsis-v-icon'; + +figma.connect( + NotificationDrawerHeader, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=3170-17841', + { + props: { + // boolean + hasActionsMenu: figma.boolean('Has actions menu', { + true: { + dropdown: ( + {}} + isOpen={false} + onOpenChange={() => {}} + popperProps={{ position: 'right' }} + toggle={(refToggle) => ( + {}} + variant="plain" + aria-label={`Basic example header kebab toggle`} + icon={} + /> + )} + > + + Item 1 + Item 2 + Item 3 + + + ), + onClose: () => {} + }, + false: { + dropdown: undefined, + onClose: undefined + } + }), + showUnreadCount: figma.boolean('Show unread count', { + true: 3, + false: NaN + }), + + // string + headingText: figma.string('Heading text') + }, + example: (props) => ( + + {props.hasActionsMenu.dropdown} + + ) + } +); diff --git a/packages/code-connect/components/NotificationDrawer/NotificationDrawerItem.figma.tsx b/packages/code-connect/components/NotificationDrawer/NotificationDrawerItem.figma.tsx new file mode 100644 index 00000000000..cef832a768e --- /dev/null +++ b/packages/code-connect/components/NotificationDrawer/NotificationDrawerItem.figma.tsx @@ -0,0 +1,68 @@ +import figma from '@figma/code-connect'; +import { + Dropdown, + DropdownItem, + DropdownList, + MenuToggle, + NotificationDrawerListItem, + NotificationDrawerListItemBody, + NotificationDrawerListItemHeader +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +// Documentation for NotificationDrawerListItem can be found at https://www.patternfly.org/components/notification-drawer + +figma.connect( + NotificationDrawerListItem, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=3164-16861', + { + props: { + // enum + isRead: figma.enum('Type', { Read: true }), + isHoverable: figma.enum('State', { Hover: true }), + variant: figma.enum('Status', { + Info: 'info', + Success: 'success', + Warning: 'warning', + Danger: 'danger' + }), + + // TODO: DESIGN: Make alert description retrievable via unique layer name or adding a prop to Noficiation Drawer Item + alertDescription: 'Description', + + // TODO: DESIGN: Make alert title retrievable via unique layer name or adding a prop to Noficiation Drawer Item + alertTitle: 'Notification title' + }, + example: (props) => ( + + + {}} + isOpen={false} + onOpenChange={() => {}} + popperProps={{ position: 'right' }} + toggle={(toggleRef) => ( + {}} + variant="plain" + aria-label={`Basic example header kebab toggle`} + icon={} + /> + )} + > + + Item 1 + Item 2 + Item 3 + + + + + {props.alertDescription} + + + ) + } +); diff --git a/packages/code-connect/components/Pagination/Pagination.figma.tsx b/packages/code-connect/components/Pagination/Pagination.figma.tsx new file mode 100644 index 00000000000..b3bf9af1c6b --- /dev/null +++ b/packages/code-connect/components/Pagination/Pagination.figma.tsx @@ -0,0 +1,31 @@ +import figma from '@figma/code-connect'; +import { Pagination } from '@patternfly/react-core'; + +// TODO: Split perPage and Page into separate properties +// Documentation for Pagination can be found at https://www.patternfly.org/components/pagination + +figma.connect( + Pagination, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=5047-695', + { + props: { + // enum + isExpanded: figma.enum('Menu', { Open: true, Closed: false }), + isCompact: figma.enum('Type', { Compact: true, Closed: false }), + + // nested + pageQuantity: figma.nestedProps('Page quantity selector', { + itemCount: figma.string('Total quantity') + }) + }, + example: (props) => ( + + ) + } +); diff --git a/packages/code-connect/components/PopOver/Popover.figma.tsx b/packages/code-connect/components/PopOver/Popover.figma.tsx new file mode 100644 index 00000000000..8a9f2ef7a5c --- /dev/null +++ b/packages/code-connect/components/PopOver/Popover.figma.tsx @@ -0,0 +1,79 @@ +import figma from '@figma/code-connect'; +import { Popover } from '@patternfly/react-core'; +import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; +import RhUiInformationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-information-fill-icon'; +import RhUiWarningFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-warning-fill-icon'; +import RhUiErrorFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-error-fill-icon'; +import BullhornIcon from '@patternfly/react-icons/dist/esm/icons/bullhorn-icon'; + +// TODO: DESIGN: Add buttons boolean to footerContent +// TODO: REACT: Add icon support +// Documentation for Popover can be found at https://www.patternfly.org/components/popover + +figma.connect( + Popover, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=5857-2066', + { + // enum + props: { + // boolean + footerContent: figma.boolean('Has footer', { + true: figma.string('Popover footer'), + false: undefined + }), + headerIcon: figma.boolean('Show header icon', { + true: , + false: undefined + }), + + // string + bodyContent: figma.string('Popover description'), + headerContent: figma.string('Popover Heading'), + + // enum + position: figma.enum('Position', { + 'Top-left': 'top-start', + 'Top-middle': 'top', + 'Top-right': 'top-end', + 'Bottom-left': 'bottom-start', + 'Bottom-middle': 'bottom', + 'Bottom-right': 'bottom-end' + }), + status: figma.enum('Status', { + Default: { + state: undefined, + icon: undefined + }, + Success: { + state: 'success', + icon: + }, + Info: { + state: 'info', + icon: + }, + Warning: { + state: 'warning', + icon: + }, + Danger: { + state: 'danger', + icon: + } + }), + + children: figma.children('*') + }, + example: (props) => ( + + ) + } +); diff --git a/packages/code-connect/components/SimpleList/SimpleList.figma.tsx b/packages/code-connect/components/SimpleList/SimpleList.figma.tsx new file mode 100644 index 00000000000..6010513926d --- /dev/null +++ b/packages/code-connect/components/SimpleList/SimpleList.figma.tsx @@ -0,0 +1,15 @@ +import figma from '@figma/code-connect'; +import { SimpleList } from '@patternfly/react-core'; + +// Documentation for SimpleList can be found at https://www.patternfly.org/components/simple-list + +figma.connect( + SimpleList, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=4410-20691', + { + props: { + children: figma.children('*') + }, + example: (props) => {props.children} + } +); diff --git a/packages/code-connect/components/SimpleList/SimpleListGroup.figma.tsx b/packages/code-connect/components/SimpleList/SimpleListGroup.figma.tsx new file mode 100644 index 00000000000..41d00a15936 --- /dev/null +++ b/packages/code-connect/components/SimpleList/SimpleListGroup.figma.tsx @@ -0,0 +1,19 @@ +import figma from '@figma/code-connect'; +import { SimpleListGroup } from '@patternfly/react-core'; + +// Documentation for SimpleListGroup can be found at https://www.patternfly.org/components/simple-list + +figma.connect( + SimpleListGroup, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=4410-20708', + { + props: { + simpleListItems: figma.children('Simple list item') + }, + example: (props) => ( + + {props.simpleListItems} + + ) + } +); diff --git a/packages/code-connect/components/SimpleList/SimpleListItem.figma.tsx b/packages/code-connect/components/SimpleList/SimpleListItem.figma.tsx new file mode 100644 index 00000000000..eeb96eaa01c --- /dev/null +++ b/packages/code-connect/components/SimpleList/SimpleListItem.figma.tsx @@ -0,0 +1,36 @@ +import figma from '@figma/code-connect'; +import { SimpleListItem } from '@patternfly/react-core'; + +// TODO: DESIGN: Add support for SimpleListGroup +// Documentation for SimpleListItem can be found at https://www.patternfly.org/components/simple-list + +figma.connect( + SimpleListItem, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=4410-20664', + { + props: { + text: figma.string('Text'), + + // enum + isActive: figma.enum('State', { + 'Selected - Light': true, + 'Selected - Dark': true + }), + isLink: figma.enum('Type', { + Default: { + component: undefined, + href: undefined + }, + Link: { + component: 'a', + href: '#' + } + }) + }, + example: (props) => ( + + {props.text} + + ) + } +); diff --git a/packages/code-connect/components/Skeleton/Skeleton.figma.tsx b/packages/code-connect/components/Skeleton/Skeleton.figma.tsx new file mode 100644 index 00000000000..dbbc5ecbb19 --- /dev/null +++ b/packages/code-connect/components/Skeleton/Skeleton.figma.tsx @@ -0,0 +1,32 @@ +import figma from '@figma/code-connect'; +import { Skeleton } from '@patternfly/react-core'; + +// Documentation for Skeleton can be found at https://www.patternfly.org/components/skeleton + +figma.connect( + Skeleton, + 'https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components?node-id=790-288&', + { + props: { + // enum + shape: figma.enum('Type', { + Default: undefined, + Rectangle: undefined, + Square: 'square', + Circle: 'circle' + }), + size: figma.enum('Size', { + S: 'sm', + M: 'md', + L: 'lg', + XL: 'xl', + '2XL': '2xl', + '3XL': '3xl', + '4XL': '4xl' + }) + }, + example: (props) => ( + + ) + } +); diff --git a/packages/code-connect/figma.config.json b/packages/code-connect/figma.config.json new file mode 100644 index 00000000000..074bc4c0752 --- /dev/null +++ b/packages/code-connect/figma.config.json @@ -0,0 +1,39 @@ +{ + "codeConnect": { + "parser": "react", + "include": [ + "components/NotificationDrawer/*.tsx", + "components/Pagination/*.tsx", + "components/Popover/*.tsx", + "components/SimpleList/*.tsx", + "components/Skeleton/*.tsx" + ], + "documentUrlSubstitutions": { + "https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/PatternFly-6--Components": "https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/branch/e1OeQDrgPKW13FswRqSP3I/PatternFly-6--Components" + }, + "paths": { + "@patternfly/react-core": "/Users/mnolting/Web/patternfly-react/packages/react-core/src", + "@patternfly/react-table": "/Users/mnolting/Web/patternfly-react/packages/react-table/src" + }, + "aliases": { + "@patternfly/react-core": "/Users/mnolting/Web/patternfly-react/packages/react-core/src", + "@patternfly/react-table": "/Users/mnolting/Web/patternfly-react/packages/react-table/src" + }, + "importPaths": { + "src/components": "src/components" + }, + "options": { + "instanceSwapper": { + "enabled": true + }, + "development": { + "enabled": true, + "verbose": true + }, + "production": { + "enabled": false + } + }, + "exclude": ["node_modules/**", "scripts/**"] + } +} diff --git a/packages/eslint-plugin-patternfly-react/CHANGELOG.md b/packages/eslint-plugin-patternfly-react/CHANGELOG.md index c617253b2d5..b2cf3039e2d 100644 --- a/packages/eslint-plugin-patternfly-react/CHANGELOG.md +++ b/packages/eslint-plugin-patternfly-react/CHANGELOG.md @@ -3,1123 +3,236 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. -# 4.27.0 (2022-01-14) +# 6.5.0 (2026-05-20) +### Reverts -### Features +- Revert "chore(release): releasing packages [ci skip]" ([7185856](https://github.com/patternfly/patternfly-react/commit/7185856d4985da5129bbabd6c460049e7048dd2a)) -* **DescriptionList:** add option to fill columns first ([#6736](https://github.com/patternfly/patternfly-react/issues/6736)) ([c955c29](https://github.com/patternfly/patternfly-react/commit/c955c2917dbc4b85ce58fac4f93845c429186e1b)) - - - - - -## 4.26.2 (2022-01-14) +# [6.5.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.5.0-prerelease.1...eslint-plugin-patternfly-react@6.5.0-prerelease.11) (2025-12-16) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.26.1 (2022-01-14) +# [6.5.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.4.0...eslint-plugin-patternfly-react@6.5.0-prerelease.1) (2025-10-30) **Note:** Version bump only for package eslint-plugin-patternfly-react +# 6.4.0 (2025-10-16) +**Note:** Version bump only for package eslint-plugin-patternfly-react - - -# 4.26.0 (2022-01-12) - - -### Features - -* **expandable-section:** added indented variation ([#6763](https://github.com/patternfly/patternfly-react/issues/6763)) ([703b922](https://github.com/patternfly/patternfly-react/commit/703b9224e43bedd5b37ec41d8f26f2939836d610)) - - - - - -## 4.25.1 (2022-01-11) - +# [6.4.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.3.1-prerelease.0...eslint-plugin-patternfly-react@6.4.0-prerelease.1) (2025-09-26) ### Bug Fixes -* **Select:** update typeahead Select children when any option attribute changes ([#6747](https://github.com/patternfly/patternfly-react/issues/6747)) ([1e03f3c](https://github.com/patternfly/patternfly-react/commit/1e03f3c6d0a7c507e33398c98863e40bb2233a62)) - - - - - -# 4.25.0 (2022-01-11) - - -### Features - -* **ToggleGroup:** support disabling all items under the parent ([#6700](https://github.com/patternfly/patternfly-react/issues/6700)) ([a60c8f3](https://github.com/patternfly/patternfly-react/commit/a60c8f3485546c797750451714a70b7e84a4ba0f)) - - - +- updated to 6.4.0-prerelease ([df46ac6](https://github.com/patternfly/patternfly-react/commit/df46ac6bed381eb3e01e5573f77d79301b02b7fa)) - -## 4.24.1 (2022-01-11) +## [6.3.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.3.0...eslint-plugin-patternfly-react@6.3.1-prerelease.0) (2025-07-28) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -# 4.24.0 (2022-01-11) - - -### Features - -* **Table:** update clickable area for checks/radios ([#6754](https://github.com/patternfly/patternfly-react/issues/6754)) ([c4f3c2d](https://github.com/patternfly/patternfly-react/commit/c4f3c2d7f515e3d6ad73d8b52238ca426281469a)) - - - - - -## 4.23.2 (2022-01-10) +# 6.3.0 (2025-07-22) **Note:** Version bump only for package eslint-plugin-patternfly-react +# [6.3.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.3.0-prerelease.0...eslint-plugin-patternfly-react@6.3.0-prerelease.1) (2025-07-22) +### Reverts +- Revert "chore(release): releasing packages [ci skip]" ([40999d7](https://github.com/patternfly/patternfly-react/commit/40999d70a7a3aeadbe8f40fe96bb01ab3a6219d4)) - -## 4.23.1 (2022-01-10) +# 6.2.0 (2025-04-07) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -# 4.23.0 (2022-01-10) - - -### Features - -* **Dropdown:** add plain-text variant support ([#6721](https://github.com/patternfly/patternfly-react/issues/6721)) ([e5000e3](https://github.com/patternfly/patternfly-react/commit/e5000e36194e36b9c6ae49efdb0a513125efcb70)) - - - - - -## 4.22.11 (2022-01-10) +# [6.2.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.2.0-prerelease.5...eslint-plugin-patternfly-react@6.2.0-prerelease.6) (2025-03-10) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.22.10 (2022-01-10) - - -### Bug Fixes - -* **Tabs:** allow href navigation from tabs ([#6755](https://github.com/patternfly/patternfly-react/issues/6755)) ([290d89a](https://github.com/patternfly/patternfly-react/commit/290d89aed2dd4517db9859cc80ef2745cb8a779b)) - - - - - -## 4.22.9 (2022-01-10) +# [6.2.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.2.0-prerelease.4...eslint-plugin-patternfly-react@6.2.0-prerelease.5) (2025-02-24) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.22.8 (2022-01-07) +# [6.2.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.2.0-prerelease.3...eslint-plugin-patternfly-react@6.2.0-prerelease.4) (2025-02-12) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.22.7 (2022-01-07) +# [6.2.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.2.0-prerelease.2...eslint-plugin-patternfly-react@6.2.0-prerelease.3) (2025-02-10) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.22.6 (2022-01-07) +# [6.2.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.2.0-prerelease.1...eslint-plugin-patternfly-react@6.2.0-prerelease.2) (2025-01-27) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.22.5 (2022-01-07) - - -### Bug Fixes - -* **jumplinks:** Updated JumpLinks demo to allow for horizontal display ([#6731](https://github.com/patternfly/patternfly-react/issues/6731)) ([f37b934](https://github.com/patternfly/patternfly-react/commit/f37b9342e678da247056c73767d5d40ff5435bda)) - - - - - -## 4.22.4 (2022-01-06) +# [6.2.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.2.0-prerelease.0...eslint-plugin-patternfly-react@6.2.0-prerelease.1) (2025-01-24) **Note:** Version bump only for package eslint-plugin-patternfly-react +# [6.2.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.1.0...eslint-plugin-patternfly-react@6.2.0-prerelease.0) (2025-01-06) +**Note:** Version bump only for package eslint-plugin-patternfly-react - - -## 4.22.3 (2022-01-06) - +# 6.1.0 (2024-12-16) ### Bug Fixes -* **TopologyControlBar:** Update screen reader className to latest ([#6739](https://github.com/patternfly/patternfly-react/issues/6739)) ([ed9da57](https://github.com/patternfly/patternfly-react/commit/ed9da575fddf9fe7af8a891972f7a66520785411)) - +- Update promote.sh to release 6.1.0 ([2b5106f](https://github.com/patternfly/patternfly-react/commit/2b5106ff88ce207d4a9ed2066fd390009e81fb79)) +# [6.1.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.1.0-prerelease.0...eslint-plugin-patternfly-react@6.1.0-prerelease.1) (2024-10-30) +### Bug Fixes +- update patternfly-react home page ([#11126](https://github.com/patternfly/patternfly-react/issues/11126)) ([51f3c8e](https://github.com/patternfly/patternfly-react/commit/51f3c8efbef93d86517df3b4c751331097d9a7c8)) -## 4.22.2 (2022-01-06) +# 6.1.0-prerelease.0 (2024-10-24) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.22.1 (2022-01-06) +# 6.0.0 (2024-10-24) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -# 4.22.0 (2022-01-05) - - -### Features - -* **Table:** allow a generic to be passed for cell props ([#6691](https://github.com/patternfly/patternfly-react/issues/6691)) ([e22c7be](https://github.com/patternfly/patternfly-react/commit/e22c7bebf630b7cd71e4dc434c593b69fa2fb2c8)) - - - - - -## 4.21.3 (2022-01-04) - - -### Bug Fixes - -* **docs:** fix broken theme-patternfly-org link ([#6726](https://github.com/patternfly/patternfly-react/issues/6726)) ([4ba15e9](https://github.com/patternfly/patternfly-react/commit/4ba15e9d9611afbb80d995e4d63f5478c4212a9e)) - - - - - -## 4.21.2 (2022-01-04) +# [6.0.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.0.0-prerelease.1...eslint-plugin-patternfly-react@6.0.0-prerelease.2) (2024-09-10) **Note:** Version bump only for package eslint-plugin-patternfly-react +# [6.0.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.2.0-alpha.7...eslint-plugin-patternfly-react@6.0.0-prerelease.1) (2024-09-07) +**Note:** Version bump only for package eslint-plugin-patternfly-react +# [5.2.0-alpha.7](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.2.0-alpha.6...eslint-plugin-patternfly-react@5.2.0-alpha.7) (2024-08-12) +- chore(eslint-plugin)!: remove dependencies from ESLint plugin (#10752) ([61a6194](https://github.com/patternfly/patternfly-react/commit/61a61941022d19f8c120db2d2712d1d707e9d5f6)), closes [#10752](https://github.com/patternfly/patternfly-react/issues/10752) [#10740](https://github.com/patternfly/patternfly-react/issues/10740) -## 4.21.1 (2022-01-04) - - -### Bug Fixes - -* **OverflowMenu:** pass HTMLDivElements props to group and control divs ([#6674](https://github.com/patternfly/patternfly-react/issues/6674)) ([e6d0d64](https://github.com/patternfly/patternfly-react/commit/e6d0d6406a07de04f4b232ca9a21247c0e9746c0)) - - - - - -# 4.21.0 (2021-12-22) - - -### Features - -* **Toolbar:** support customizing text in ToolbarChipGroupContent ([#6694](https://github.com/patternfly/patternfly-react/issues/6694)) ([24266ad](https://github.com/patternfly/patternfly-react/commit/24266adf569c027574abd1503b5e46974220349a)) - - - - - -## 4.20.5 (2021-12-16) - - -### Bug Fixes - -* **LogViewer:** fix the issue that scrollbar could compress the content of the logs ([#6702](https://github.com/patternfly/patternfly-react/issues/6702)) ([11aab1f](https://github.com/patternfly/patternfly-react/commit/11aab1f71a1aa9959cf14b887ab55b845a794a00)) - - +### BREAKING CHANGES +- this removes the bundled dependencies and pre-defined rules from the ESLint 'reccomended' configuration. +Signed-off-by: Jon Koops -## 4.20.4 (2021-12-14) +# [5.2.0-alpha.6](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.2.0-alpha.5...eslint-plugin-patternfly-react@5.2.0-alpha.6) (2024-08-08) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.20.3 (2021-12-13) +# [5.2.0-alpha.5](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.2.0-alpha.4...eslint-plugin-patternfly-react@5.2.0-alpha.5) (2024-07-22) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.20.2 (2021-12-13) +# [5.2.0-alpha.4](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.2.0-alpha.3...eslint-plugin-patternfly-react@5.2.0-alpha.4) (2024-06-25) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.20.1 (2021-12-09) +# [5.2.0-alpha.3](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.2.0-alpha.2...eslint-plugin-patternfly-react@5.2.0-alpha.3) (2024-05-31) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -# 4.20.0 (2021-12-09) - - -### Features - -* **Popover:** add composable header and alert variants ([#6664](https://github.com/patternfly/patternfly-react/issues/6664)) ([9028e8b](https://github.com/patternfly/patternfly-react/commit/9028e8ba5d674bde6a7e29532f7926e200dd632a)) - - - - - -## 4.19.1 (2021-12-08) +# 5.2.0-alpha.2 (2024-04-22) **Note:** Version bump only for package eslint-plugin-patternfly-react +# 5.3.0-prerelease.0 (2024-02-02) - - - -# 4.19.0 (2021-12-08) - - -### Features - -* **DualListSelector:** add composable tree example ([#6652](https://github.com/patternfly/patternfly-react/issues/6652)) ([5fe977b](https://github.com/patternfly/patternfly-react/commit/5fe977becb5dea615724abf846f315e50931c188)) - - - - - -## 4.18.1 (2021-12-07) +# 5.2.0 (2024-02-02) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -# 4.18.0 (2021-12-06) - - -### Features - -* **Card:** Add disabled card and clean up props ([#6659](https://github.com/patternfly/patternfly-react/issues/6659)) ([86f225a](https://github.com/patternfly/patternfly-react/commit/86f225ab2e02d617e2d380c4a7f7593037c50e84)) - - - - - -# 4.17.0 (2021-12-06) - - -### Features - -* **MenuToggle:** add plain with text variant ([#6627](https://github.com/patternfly/patternfly-react/issues/6627)) ([1f4ca5e](https://github.com/patternfly/patternfly-react/commit/1f4ca5e36d7077da3ff3e6918874048c784216e0)) - - - - - -# 4.16.0 (2021-12-06) - - -### Features - -* **Dropdown:** add toggle variants ([#6651](https://github.com/patternfly/patternfly-react/issues/6651)) ([6414309](https://github.com/patternfly/patternfly-react/commit/64143094aec86aed86adb320e059d987af4f5f24)) - - - - - -## 4.15.1 (2021-12-06) +## 5.2.1 (2024-02-02) **Note:** Version bump only for package eslint-plugin-patternfly-react +## 5.2.1-prerelease.0 (2024-02-02) +### Reverts +- Revert release attempt (#10062) ([1cd0691](https://github.com/patternfly/patternfly-react/commit/1cd0691ebc90b323682c54b43295a6afd174a120)), closes [#10062](https://github.com/patternfly/patternfly-react/issues/10062) - -# 4.15.0 (2021-12-03) - - -### Features - -* **Select:** add ability to persist filtered children state ([#6670](https://github.com/patternfly/patternfly-react/issues/6670)) ([f618577](https://github.com/patternfly/patternfly-react/commit/f618577582e389409978bd1d6512ca0cf5d855cf)) - - - - - -## 4.14.17 (2021-12-03) - - -### Bug Fixes - -* **Slider:** fixed examples with custom steps and input ([#6662](https://github.com/patternfly/patternfly-react/issues/6662)) ([b4cab38](https://github.com/patternfly/patternfly-react/commit/b4cab38a2492564bf91e3711ce322951bcc6a051)) - - - - - -## 4.14.16 (2021-12-02) +# 5.2.0-alpha.1 (2024-03-08) **Note:** Version bump only for package eslint-plugin-patternfly-react +# [5.2.0-alpha.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@6.0.0-alpha.1...eslint-plugin-patternfly-react@5.2.0-alpha.0) (2023-11-16) +### Reverts +- Revert "Merge remote-tracking branch 'upstream/main' into v6" (#9791) ([b7e8065](https://github.com/patternfly/patternfly-react/commit/b7e80650d3e4cad7a657f6e5a3177485ca4f8c26)), closes [#9791](https://github.com/patternfly/patternfly-react/issues/9791) - -## 4.14.15 (2021-12-02) - +# 6.0.0-alpha.1 (2023-09-29) ### Bug Fixes -* **Tile:** fix selecting tile in tile demo ([#6653](https://github.com/patternfly/patternfly-react/issues/6653)) ([e12e44d](https://github.com/patternfly/patternfly-react/commit/e12e44d4b623de305b7df04174144a9496d282a7)) - +- Release alphas from v6 and rebase from main ([#9692](https://github.com/patternfly/patternfly-react/issues/9692)) ([bb022ff](https://github.com/patternfly/patternfly-react/commit/bb022ffc65da8e8c5b5c984412f936cea9424676)), closes [#9651](https://github.com/patternfly/patternfly-react/issues/9651) [#9627](https://github.com/patternfly/patternfly-react/issues/9627) [#9555](https://github.com/patternfly/patternfly-react/issues/9555) [#9543](https://github.com/patternfly/patternfly-react/issues/9543) [#9578](https://github.com/patternfly/patternfly-react/issues/9578) [#9519](https://github.com/patternfly/patternfly-react/issues/9519) [#9603](https://github.com/patternfly/patternfly-react/issues/9603) [#9655](https://github.com/patternfly/patternfly-react/issues/9655) [#9614](https://github.com/patternfly/patternfly-react/issues/9614) [#9606](https://github.com/patternfly/patternfly-react/issues/9606) [#9628](https://github.com/patternfly/patternfly-react/issues/9628) [#9635](https://github.com/patternfly/patternfly-react/issues/9635) [#9649](https://github.com/patternfly/patternfly-react/issues/9649) [#9642](https://github.com/patternfly/patternfly-react/issues/9642) [#9633](https://github.com/patternfly/patternfly-react/issues/9633) [#9637](https://github.com/patternfly/patternfly-react/issues/9637) [#9584](https://github.com/patternfly/patternfly-react/issues/9584) [#9284](https://github.com/patternfly/patternfly-react/issues/9284) +# 5.3.0-prerelease.0 (2024-02-02) +# 5.2.0 (2024-02-02) +**Note:** Version bump only for package eslint-plugin-patternfly-react -## 4.14.14 (2021-12-01) +## 5.2.1 (2024-02-02) **Note:** Version bump only for package eslint-plugin-patternfly-react +## 5.2.1-prerelease.0 (2024-02-02) +### Reverts +- Revert release attempt (#10062) ([1cd0691](https://github.com/patternfly/patternfly-react/commit/1cd0691ebc90b323682c54b43295a6afd174a120)), closes [#10062](https://github.com/patternfly/patternfly-react/issues/10062) - -## 4.14.13 (2021-11-30) +# [5.2.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.1.1...eslint-plugin-patternfly-react@5.2.0-prerelease.0) (2023-10-05) **Note:** Version bump only for package eslint-plugin-patternfly-react +## 5.1.1 (2023-10-05) +**Note:** Version bump only for package eslint-plugin-patternfly-react - - -## 4.14.12 (2021-11-30) - +## 5.1.1-prerelease.1 (2023-08-29) ### Bug Fixes -* **action-list:** added support for classname ([#6647](https://github.com/patternfly/patternfly-react/issues/6647)) ([dd3d2ce](https://github.com/patternfly/patternfly-react/commit/dd3d2ce32b4d3e7562faf465abdc508e17f097d9)) - +- **deps:** update dependency eslint-config-prettier to v9 ([#9464](https://github.com/patternfly/patternfly-react/issues/9464)) ([9a43090](https://github.com/patternfly/patternfly-react/commit/9a430903fb38694db3f08e9029002b9ca246d906)) +- **deps:** update dependency eslint-plugin-prettier to v5 ([#9458](https://github.com/patternfly/patternfly-react/issues/9458)) ([6c0646b](https://github.com/patternfly/patternfly-react/commit/6c0646b2bb337e1b089321addc100c25e623f08e)) +- **deps:** update dependency eslint-plugin-prettier to v5 ([#9473](https://github.com/patternfly/patternfly-react/issues/9473)) ([507fb64](https://github.com/patternfly/patternfly-react/commit/507fb6403e43fee098b08a26ed536c0d78452d01)) +### Reverts +- Revert "fix(deps): update dependency eslint-plugin-prettier to v5 (#9458)" (#9472) ([c797be9](https://github.com/patternfly/patternfly-react/commit/c797be94af1a1cc885df7a53567bb659030ed16c)), closes [#9458](https://github.com/patternfly/patternfly-react/issues/9458) [#9472](https://github.com/patternfly/patternfly-react/issues/9472) +# 5.0.0 (2023-07-27) -## 4.14.11 (2021-11-30) +# [5.1.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@5.0.0...eslint-plugin-patternfly-react@5.1.0-prerelease.0) (2023-07-27) **Note:** Version bump only for package eslint-plugin-patternfly-react - - - - -## 4.14.10 (2021-11-23) +# 5.0.0 (2023-07-27) **Note:** Version bump only for package eslint-plugin-patternfly-react +# 5.0.0-prerelease.2 (2023-06-13) +### Bug Fixes +- **docs:** update use of deprecated tag and clean up changelogs ([#9259](https://github.com/patternfly/patternfly-react/issues/9259)) ([8de83dc](https://github.com/patternfly/patternfly-react/commit/8de83dc3b2fb88094fd3c21bda2ed6e371986cba)) +# 5.0.0-prerelease.1 (2023-06-06) -## 4.14.9 (2021-11-19) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - +### Bug Fixes -## 4.14.8 (2021-11-19) +- **release:** dryrun publishing prereleases ([#9242](https://github.com/patternfly/patternfly-react/issues/9242)) ([e4c35f1](https://github.com/patternfly/patternfly-react/commit/e4c35f14cd57be132179e51ae2bb223600a35f0e)) -**Note:** Version bump only for package eslint-plugin-patternfly-react +## 4.80.5-alpha.1 (2023-05-04) +### Bug Fixes +- **deps:** update dependency eslint-config-standard to v17 ([#9042](https://github.com/patternfly/patternfly-react/issues/9042)) ([89ce7f1](https://github.com/patternfly/patternfly-react/commit/89ce7f1499977fd70f441e0b449456e081421bee)) +- **deps:** update dependency eslint-config-standard-jsx to v11 ([#9043](https://github.com/patternfly/patternfly-react/issues/9043)) ([11df5e3](https://github.com/patternfly/patternfly-react/commit/11df5e357ac58c75524c75458e72333b7379aac7)) +- **deps:** update dependency eslint-config-standard-react to v13 ([#9044](https://github.com/patternfly/patternfly-react/issues/9044)) ([9d37fc7](https://github.com/patternfly/patternfly-react/commit/9d37fc735dbc0ee3b6705cf957748cdd8cf217aa)) +- **deps:** update dependency eslint-plugin-jest to v27 ([#9045](https://github.com/patternfly/patternfly-react/issues/9045)) ([a72f9aa](https://github.com/patternfly/patternfly-react/commit/a72f9aabcca56d6adbfef4e54c32a1579bd62cc8)) +- **deps:** update dependency eslint-plugin-node to v11 ([#9046](https://github.com/patternfly/patternfly-react/issues/9046)) ([2c52a92](https://github.com/patternfly/patternfly-react/commit/2c52a92e7d9112e283fdaaf4f55038d67d96116d)) +- **deps:** update dependency eslint-plugin-prettier to v4 ([#9047](https://github.com/patternfly/patternfly-react/issues/9047)) ([bbad5ee](https://github.com/patternfly/patternfly-react/commit/bbad5eefcd80a6f9c19d35b6f6cb348db8fd4800)) +- **deps:** update dependency eslint-plugin-promise to v6 ([#9049](https://github.com/patternfly/patternfly-react/issues/9049)) ([479024b](https://github.com/patternfly/patternfly-react/commit/479024b101713ed8acbc5bc97f46a0d6ac40ea07)) +- **deps:** update dependency eslint-plugin-rulesdir to ^0.2.0 ([#9039](https://github.com/patternfly/patternfly-react/issues/9039)) ([d29d01e](https://github.com/patternfly/patternfly-react/commit/d29d01eb0b1640d3fe6e560948ad7e49bdc172a0)) +- **deps:** update dependency eslint-plugin-standard to v4 ([#9050](https://github.com/patternfly/patternfly-react/issues/9050)) ([da9acf1](https://github.com/patternfly/patternfly-react/commit/da9acf1d34d874c456f85164ed5e20c1941345ef)) - - -## 4.14.7 (2021-11-18) - - -### Bug Fixes - -* **pagination:** updated toggleTemplate prop description to include ofWord prop ([#6622](https://github.com/patternfly/patternfly-react/issues/6622)) ([26733a6](https://github.com/patternfly/patternfly-react/commit/26733a6a256ad0e873afbc268a712027470fdeaa)) - - - - - -## 4.14.6 (2021-11-18) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.14.5 (2021-11-17) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.14.4 (2021-11-15) - - -### Bug Fixes - -* **FileUpload:** Downgrade react-dropzone back to 9.0.0 to avoid a breaking type change, fix behavior regressions ([#6610](https://github.com/patternfly/patternfly-react/issues/6610)) ([574bf4f](https://github.com/patternfly/patternfly-react/commit/574bf4ff3ccf7f67ce750bc48067eaf826e99990)) - - - - - -## 4.14.3 (2021-11-15) - - -### Bug Fixes - -* **Menu:** allow maxMenuHeight with Scrollabe ([#6608](https://github.com/patternfly/patternfly-react/issues/6608)) ([8c1f12c](https://github.com/patternfly/patternfly-react/commit/8c1f12c2b0e86bbc5ba1071db3ebf29fee7421a0)) - - - - - -## 4.14.2 (2021-11-15) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.14.1 (2021-11-15) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -# 4.14.0 (2021-11-12) - - -### Features - -* **card:** added hoverable/selectable/selected-raised variant ([#6565](https://github.com/patternfly/patternfly-react/issues/6565)) ([8c60568](https://github.com/patternfly/patternfly-react/commit/8c60568ba4fa18398fed636710e222ce506de82c)) - - - - - -## 4.13.2 (2021-11-12) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.13.1 (2021-11-12) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -# 4.13.0 (2021-11-11) - - -### Features - -* **ComposableTable:** add sticky columns and nested headers ([#6538](https://github.com/patternfly/patternfly-react/issues/6538)) ([f11245b](https://github.com/patternfly/patternfly-react/commit/f11245bfccc8c6c02a9d5545a69ed533743cc552)) - - - - - -# 4.12.0 (2021-11-11) - - -### Features - -* **contextselector:** added support for context selector items as links ([#6554](https://github.com/patternfly/patternfly-react/issues/6554)) ([c465388](https://github.com/patternfly/patternfly-react/commit/c4653881eee0cd8ec8e3a7125bbef0bded9f2de0)) - - - - - -# 4.11.0 (2021-11-11) - - -### Features - -* **Navigation:** Added exemple with third level ([#6564](https://github.com/patternfly/patternfly-react/issues/6564)) ([c30da53](https://github.com/patternfly/patternfly-react/commit/c30da532855118f705c8cfc87c545bb1eea11ebb)) - - - - - -# 4.10.0 (2021-11-11) - - -### Features - -* enhance type correctness of CodeEditor ([#6579](https://github.com/patternfly/patternfly-react/issues/6579)) ([e1ad65c](https://github.com/patternfly/patternfly-react/commit/e1ad65c225968d5a9c74019d19e4a3c5e2666926)) - - - - - -## 4.9.4 (2021-11-10) - - -### Bug Fixes - -* **jumplinks:** fixed to always set clicked item as active ([#6542](https://github.com/patternfly/patternfly-react/issues/6542)) ([845c98f](https://github.com/patternfly/patternfly-react/commit/845c98f5f3df8aa9b6acc190707c5f1d7bf3ca38)) - - - - - -## 4.9.3 (2021-11-10) - - -### Bug Fixes - -* **Menu:** stop passing disableHover to DrilldownMenu DOM ([#6571](https://github.com/patternfly/patternfly-react/issues/6571)) ([63dcf25](https://github.com/patternfly/patternfly-react/commit/63dcf256723848ff3789828fc0a5f86d5009fc87)) - - - - - -## 4.9.2 (2021-11-10) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.9.1 (2021-11-10) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -# 4.9.0 (2021-11-09) - - -### Features - -* **Table:** set default sort direction ([#6544](https://github.com/patternfly/patternfly-react/issues/6544)) ([9ee4942](https://github.com/patternfly/patternfly-react/commit/9ee49428c8e1041721f2a09f8176a5aba3335049)) - - - - - -## 4.8.4 (2021-11-09) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.8.3 (2021-11-08) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.8.2 (2021-11-08) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.8.1 (2021-11-08) - - -### Bug Fixes - -* **acccessconsoles:** use object type Select options values in order to not mix displayed text with option keys ([#6496](https://github.com/patternfly/patternfly-react/issues/6496)) ([975c8e1](https://github.com/patternfly/patternfly-react/commit/975c8e14d7ea8c53eb4048ea6ef73e804b3ad2be)) - - - - - -# 4.8.0 (2021-11-04) - - -### Features - -* **log-viewer:** support ANSI color ([#6519](https://github.com/patternfly/patternfly-react/issues/6519)) ([936a699](https://github.com/patternfly/patternfly-react/commit/936a699b0514a492d3c40be08932fb7bab275cce)) - - - - - -## 4.7.11 (2021-11-01) - - -### Bug Fixes - -* **AboutModal:** allow to disable FocusTrap ([#6509](https://github.com/patternfly/patternfly-react/issues/6509)) ([72536e1](https://github.com/patternfly/patternfly-react/commit/72536e1f73641ff3f19f865f08dbb41ad0ee7b9f)) - - - - - -## 4.7.10 (2021-10-29) - - -### Bug Fixes - -* **Banner:** forward props ([#6511](https://github.com/patternfly/patternfly-react/issues/6511)) ([e36c890](https://github.com/patternfly/patternfly-react/commit/e36c89077afa82340994c0e3c0fc929e601e01bc)) - - - - - -## 4.7.9 (2021-10-28) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.7.8 (2021-10-27) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.7.7 (2021-10-27) - - -### Bug Fixes - -* change transformer cjs package to private ([#6515](https://github.com/patternfly/patternfly-react/issues/6515)) ([efcb357](https://github.com/patternfly/patternfly-react/commit/efcb3573b71541328ce2b16caa80ce33b2a62131)) - - - - - -## 4.7.6 (2021-10-26) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.7.5 (2021-10-26) - - -### Bug Fixes - -* **tokens:** added check for no matching var to avoid infinite loop ([#6502](https://github.com/patternfly/patternfly-react/issues/6502)) ([99605c2](https://github.com/patternfly/patternfly-react/commit/99605c213f12490d0abe75910e05c3e6da26a1f3)) - - - - - -## 4.7.4 (2021-10-26) - - -### Bug Fixes - -* add transformer package ([#6507](https://github.com/patternfly/patternfly-react/issues/6507)) ([daffd28](https://github.com/patternfly/patternfly-react/commit/daffd2864388abe63e625f962a8b38c2b7056209)) - - - - - -## 4.7.3 (2021-10-26) - - -### Bug Fixes - -* **transformer:** publish transformer in patternfly org ([#6506](https://github.com/patternfly/patternfly-react/issues/6506)) ([b739af3](https://github.com/patternfly/patternfly-react/commit/b739af318400b41d4e9a53bdff6232ecc176916e)) - - - - - -## 4.7.2 (2021-10-26) - - -### Bug Fixes - -* **readme:** update react-core readme ([#6505](https://github.com/patternfly/patternfly-react/issues/6505)) ([d4f9a11](https://github.com/patternfly/patternfly-react/commit/d4f9a114584eea7ab67873f199e80b348886e14b)) - - - - - -## 4.7.1 (2021-10-26) - - -### Bug Fixes - -* **DualListSelector:** account for duplicate folders ([#6499](https://github.com/patternfly/patternfly-react/issues/6499)) ([e531e68](https://github.com/patternfly/patternfly-react/commit/e531e68e7adc58459b3630f5c915ed69e3021012)) - - - - - -# 4.7.0 (2021-10-26) - - -### Features - -* **toolbar:** add sticky top modifier to toolbar ([#6447](https://github.com/patternfly/patternfly-react/issues/6447)) ([fe7605a](https://github.com/patternfly/patternfly-react/commit/fe7605a67428b43ec00b3cb2117270296576737c)) - - - - - -## 4.6.1 (2021-10-26) - - -### Bug Fixes - -* **types:** SelectOptionProp made optional ([#6503](https://github.com/patternfly/patternfly-react/issues/6503)) ([716ac80](https://github.com/patternfly/patternfly-react/commit/716ac80e2414507d589ee3002fc0cea0068ae59c)) - - - - - -# 4.6.0 (2021-10-26) - - -### Features - -* **TextInputGroup:** add text input group ([#6482](https://github.com/patternfly/patternfly-react/issues/6482)) ([a02fd4f](https://github.com/patternfly/patternfly-react/commit/a02fd4fe3345245b2252ee5a261f5b1460490642)), closes [patternfly/patternfly-react#6409](https://github.com/patternfly/patternfly-react/issues/6409) - - - - - -## 4.5.4 (2021-10-26) - - -### Bug Fixes - -* **KebabToggle:** adds event to onToggle definition ([#6490](https://github.com/patternfly/patternfly-react/issues/6490)) ([0441575](https://github.com/patternfly/patternfly-react/commit/04415757917062aa13c06b34bd94ef38c2334088)) - - - - - -## 4.5.3 (2021-10-26) - - -### Bug Fixes - -* **Modal:** test clean up ([#6489](https://github.com/patternfly/patternfly-react/issues/6489)) ([c8eaa7c](https://github.com/patternfly/patternfly-react/commit/c8eaa7c838fbedb98ea0f38e4f535488040a72e2)) - - - - - -## 4.5.2 (2021-10-25) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.5.1 (2021-10-25) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -# 4.5.0 (2021-10-25) - - -### Features - -* **Tabs:** Added support for tab content body with padding, added tabs open and tab secondary tabs demos ([#6484](https://github.com/patternfly/patternfly-react/issues/6484)) ([0ccbe9d](https://github.com/patternfly/patternfly-react/commit/0ccbe9d1e6e0dac0730466c92a90fe2cd9f6560d)) - - - - - -## 4.4.1 (2021-10-21) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -# 4.4.0 (2021-10-21) - - -### Features - -* **label:** added compact label, updated horizontal grid card demo ([#6448](https://github.com/patternfly/patternfly-react/issues/6448)) ([89e0431](https://github.com/patternfly/patternfly-react/commit/89e04317924282140606d45f2292aa3f658b4b6c)) - - - - - -## 4.3.1 (2021-10-21) - - -### Bug Fixes - -* **DescriptionListGroup:** forward props to DOM ([#6466](https://github.com/patternfly/patternfly-react/issues/6466)) ([b78e2aa](https://github.com/patternfly/patternfly-react/commit/b78e2aa9c0360ce8418f6e7b55274ea1a50de518)) - - - - - -# 4.3.0 (2021-10-20) - - -### Features - -* **Progress:** allow node titles ([#6470](https://github.com/patternfly/patternfly-react/issues/6470)) ([46d5252](https://github.com/patternfly/patternfly-react/commit/46d52523ad5111bb11729c2750abe9aeb35d9326)) - - - - - -# 4.2.0 (2021-10-20) - - -### Features - -* **DualListSelector:** add disabled flag ([#6442](https://github.com/patternfly/patternfly-react/issues/6442)) ([85e1314](https://github.com/patternfly/patternfly-react/commit/85e131435be12c2df79336e9fa56987ed3717417)) - - - - - -## 4.1.10 (2021-10-20) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## 4.1.9 (2021-10-20) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## [4.1.8](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.7...eslint-plugin-patternfly-react@4.1.8) (2021-08-19) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## [4.1.7](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.6...eslint-plugin-patternfly-react@4.1.7) (2021-06-30) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## [4.1.6](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.5...eslint-plugin-patternfly-react@4.1.6) (2021-06-30) - - -### Bug Fixes - -* **ci:** change master branch to main ([4ac4129](https://github.com/patternfly/patternfly-react/commit/4ac4129e8da9a37367ea7612019f8d7af1ed8836)) - - - - - -## [4.1.5](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.4...eslint-plugin-patternfly-react@4.1.5) (2020-11-20) - - -### Bug Fixes - -* **eslint:** fix @patternfly/react-icons/createIcon differently ([#5163](https://github.com/patternfly/patternfly-react/issues/5163)) ([271464d](https://github.com/patternfly/patternfly-react/commit/271464d3293704b29a24e5a4f140deb2b3985cda)) - - - - - -## [4.1.4](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.3...eslint-plugin-patternfly-react@4.1.4) (2020-09-22) - - -### Bug Fixes - -* **eslint-plugin:** upgrade react-hooks ([#4857](https://github.com/patternfly/patternfly-react/issues/4857)) ([8c89cc1](https://github.com/patternfly/patternfly-react/commit/8c89cc130bf195fb892946a5a8f6730a7af1c3a2)) - - - - - -## [4.1.3](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.2...eslint-plugin-patternfly-react@4.1.3) (2020-08-24) - - -### Bug Fixes - -* **docs:** use ids and h3s ([#4720](https://github.com/patternfly/patternfly-react/issues/4720)) ([a3f684f](https://github.com/patternfly/patternfly-react/commit/a3f684fa23cfce3d8e79b86206773292790cec5c)) - - - - - -## [4.1.2](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.1...eslint-plugin-patternfly-react@4.1.2) (2020-07-17) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## [4.1.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@4.1.0...eslint-plugin-patternfly-react@4.1.1) (2020-06-15) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -# [4.1.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@0.4.1...eslint-plugin-patternfly-react@4.1.0) (2020-05-15) - - -### Features - -* **master:** merge v4 ([#4255](https://github.com/patternfly/patternfly-react/issues/4255)) ([567c0b8](https://github.com/patternfly/patternfly-react/commit/567c0b88b10d2cd629ce380745a24dacdf9dd3d1)), closes [#3868](https://github.com/patternfly/patternfly-react/issues/3868) [#3915](https://github.com/patternfly/patternfly-react/issues/3915) [#3921](https://github.com/patternfly/patternfly-react/issues/3921) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3843](https://github.com/patternfly/patternfly-react/issues/3843) [#3884](https://github.com/patternfly/patternfly-react/issues/3884) [#3609](https://github.com/patternfly/patternfly-react/issues/3609) [#3880](https://github.com/patternfly/patternfly-react/issues/3880) [#3865](https://github.com/patternfly/patternfly-react/issues/3865) [#3894](https://github.com/patternfly/patternfly-react/issues/3894) [#3897](https://github.com/patternfly/patternfly-react/issues/3897) [#3892](https://github.com/patternfly/patternfly-react/issues/3892) [#3891](https://github.com/patternfly/patternfly-react/issues/3891) [#3908](https://github.com/patternfly/patternfly-react/issues/3908) [#3910](https://github.com/patternfly/patternfly-react/issues/3910) [#3861](https://github.com/patternfly/patternfly-react/issues/3861) [#3877](https://github.com/patternfly/patternfly-react/issues/3877) [#3916](https://github.com/patternfly/patternfly-react/issues/3916) [#3886](https://github.com/patternfly/patternfly-react/issues/3886) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3927](https://github.com/patternfly/patternfly-react/issues/3927) [#3933](https://github.com/patternfly/patternfly-react/issues/3933) [#3221](https://github.com/patternfly/patternfly-react/issues/3221) [#3873](https://github.com/patternfly/patternfly-react/issues/3873) [#3928](https://github.com/patternfly/patternfly-react/issues/3928) [#3929](https://github.com/patternfly/patternfly-react/issues/3929) [#2582](https://github.com/patternfly/patternfly-react/issues/2582) [#3296](https://github.com/patternfly/patternfly-react/issues/3296) [#3924](https://github.com/patternfly/patternfly-react/issues/3924) [#1529](https://github.com/patternfly/patternfly-react/issues/1529) [#3903](https://github.com/patternfly/patternfly-react/issues/3903) [#3904](https://github.com/patternfly/patternfly-react/issues/3904) [#3974](https://github.com/patternfly/patternfly-react/issues/3974) [#3970](https://github.com/patternfly/patternfly-react/issues/3970) [#3920](https://github.com/patternfly/patternfly-react/issues/3920) [#3945](https://github.com/patternfly/patternfly-react/issues/3945) [#3978](https://github.com/patternfly/patternfly-react/issues/3978) [#3962](https://github.com/patternfly/patternfly-react/issues/3962) [#3975](https://github.com/patternfly/patternfly-react/issues/3975) [#3906](https://github.com/patternfly/patternfly-react/issues/3906) [#3870](https://github.com/patternfly/patternfly-react/issues/3870) [#3958](https://github.com/patternfly/patternfly-react/issues/3958) [#3922](https://github.com/patternfly/patternfly-react/issues/3922) [#3985](https://github.com/patternfly/patternfly-react/issues/3985) [#3991](https://github.com/patternfly/patternfly-react/issues/3991) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3843](https://github.com/patternfly/patternfly-react/issues/3843) [#3884](https://github.com/patternfly/patternfly-react/issues/3884) [#3609](https://github.com/patternfly/patternfly-react/issues/3609) [#3880](https://github.com/patternfly/patternfly-react/issues/3880) [#3865](https://github.com/patternfly/patternfly-react/issues/3865) [#3894](https://github.com/patternfly/patternfly-react/issues/3894) [#3897](https://github.com/patternfly/patternfly-react/issues/3897) [#3892](https://github.com/patternfly/patternfly-react/issues/3892) [#3891](https://github.com/patternfly/patternfly-react/issues/3891) [#3908](https://github.com/patternfly/patternfly-react/issues/3908) [#3910](https://github.com/patternfly/patternfly-react/issues/3910) [#3861](https://github.com/patternfly/patternfly-react/issues/3861) [#3877](https://github.com/patternfly/patternfly-react/issues/3877) [#3916](https://github.com/patternfly/patternfly-react/issues/3916) [#3844](https://github.com/patternfly/patternfly-react/issues/3844) [#3919](https://github.com/patternfly/patternfly-react/issues/3919) [#3923](https://github.com/patternfly/patternfly-react/issues/3923) [#3838](https://github.com/patternfly/patternfly-react/issues/3838) [#3895](https://github.com/patternfly/patternfly-react/issues/3895) [#3896](https://github.com/patternfly/patternfly-react/issues/3896) [#3771](https://github.com/patternfly/patternfly-react/issues/3771) [#3940](https://github.com/patternfly/patternfly-react/issues/3940) [#3941](https://github.com/patternfly/patternfly-react/issues/3941) [#3441](https://github.com/patternfly/patternfly-react/issues/3441) [#3950](https://github.com/patternfly/patternfly-react/issues/3950) [#3642](https://github.com/patternfly/patternfly-react/issues/3642) [#3964](https://github.com/patternfly/patternfly-react/issues/3964) [#3968](https://github.com/patternfly/patternfly-react/issues/3968) [#3967](https://github.com/patternfly/patternfly-react/issues/3967) [#3971](https://github.com/patternfly/patternfly-react/issues/3971) [#3942](https://github.com/patternfly/patternfly-react/issues/3942) [#3898](https://github.com/patternfly/patternfly-react/issues/3898) [#3898](https://github.com/patternfly/patternfly-react/issues/3898) [#3976](https://github.com/patternfly/patternfly-react/issues/3976) [#3889](https://github.com/patternfly/patternfly-react/issues/3889) [#3641](https://github.com/patternfly/patternfly-react/issues/3641) [#3982](https://github.com/patternfly/patternfly-react/issues/3982) [#3979](https://github.com/patternfly/patternfly-react/issues/3979) [#3989](https://github.com/patternfly/patternfly-react/issues/3989) [#4017](https://github.com/patternfly/patternfly-react/issues/4017) [#4022](https://github.com/patternfly/patternfly-react/issues/4022) [#4014](https://github.com/patternfly/patternfly-react/issues/4014) [#4048](https://github.com/patternfly/patternfly-react/issues/4048) [#4050](https://github.com/patternfly/patternfly-react/issues/4050) [#4051](https://github.com/patternfly/patternfly-react/issues/4051) [#4058](https://github.com/patternfly/patternfly-react/issues/4058) [#4030](https://github.com/patternfly/patternfly-react/issues/4030) [#4031](https://github.com/patternfly/patternfly-react/issues/4031) [#3996](https://github.com/patternfly/patternfly-react/issues/3996) [#4001](https://github.com/patternfly/patternfly-react/issues/4001) [#4004](https://github.com/patternfly/patternfly-react/issues/4004) [#4066](https://github.com/patternfly/patternfly-react/issues/4066) [#4021](https://github.com/patternfly/patternfly-react/issues/4021) [#4061](https://github.com/patternfly/patternfly-react/issues/4061) [#4026](https://github.com/patternfly/patternfly-react/issues/4026) [#4069](https://github.com/patternfly/patternfly-react/issues/4069) [#4073](https://github.com/patternfly/patternfly-react/issues/4073) [#4036](https://github.com/patternfly/patternfly-react/issues/4036) [#4019](https://github.com/patternfly/patternfly-react/issues/4019) [#4081](https://github.com/patternfly/patternfly-react/issues/4081) [#4033](https://github.com/patternfly/patternfly-react/issues/4033) [#4065](https://github.com/patternfly/patternfly-react/issues/4065) [#4078](https://github.com/patternfly/patternfly-react/issues/4078) [#4032](https://github.com/patternfly/patternfly-react/issues/4032) [#4029](https://github.com/patternfly/patternfly-react/issues/4029) [#4064](https://github.com/patternfly/patternfly-react/issues/4064) [#4063](https://github.com/patternfly/patternfly-react/issues/4063) [#2593](https://github.com/patternfly/patternfly-react/issues/2593) [#4076](https://github.com/patternfly/patternfly-react/issues/4076) [#4099](https://github.com/patternfly/patternfly-react/issues/4099) [#4038](https://github.com/patternfly/patternfly-react/issues/4038) [#4116](https://github.com/patternfly/patternfly-react/issues/4116) [#3960](https://github.com/patternfly/patternfly-react/issues/3960) [#4121](https://github.com/patternfly/patternfly-react/issues/4121) [#4123](https://github.com/patternfly/patternfly-react/issues/4123) [#4025](https://github.com/patternfly/patternfly-react/issues/4025) [#4126](https://github.com/patternfly/patternfly-react/issues/4126) [#4122](https://github.com/patternfly/patternfly-react/issues/4122) [#4086](https://github.com/patternfly/patternfly-react/issues/4086) [#4127](https://github.com/patternfly/patternfly-react/issues/4127) [#4129](https://github.com/patternfly/patternfly-react/issues/4129) [#4111](https://github.com/patternfly/patternfly-react/issues/4111) [#4136](https://github.com/patternfly/patternfly-react/issues/4136) [#4138](https://github.com/patternfly/patternfly-react/issues/4138) [#4141](https://github.com/patternfly/patternfly-react/issues/4141) [#4145](https://github.com/patternfly/patternfly-react/issues/4145) [#4034](https://github.com/patternfly/patternfly-react/issues/4034) [#4144](https://github.com/patternfly/patternfly-react/issues/4144) [#4152](https://github.com/patternfly/patternfly-react/issues/4152) [#4158](https://github.com/patternfly/patternfly-react/issues/4158) [#4157](https://github.com/patternfly/patternfly-react/issues/4157) [#4156](https://github.com/patternfly/patternfly-react/issues/4156) [#4147](https://github.com/patternfly/patternfly-react/issues/4147) [#4159](https://github.com/patternfly/patternfly-react/issues/4159) [#4170](https://github.com/patternfly/patternfly-react/issues/4170) [#4142](https://github.com/patternfly/patternfly-react/issues/4142) [#4175](https://github.com/patternfly/patternfly-react/issues/4175) [#4176](https://github.com/patternfly/patternfly-react/issues/4176) [#4187](https://github.com/patternfly/patternfly-react/issues/4187) [#4188](https://github.com/patternfly/patternfly-react/issues/4188) [#4140](https://github.com/patternfly/patternfly-react/issues/4140) [#4193](https://github.com/patternfly/patternfly-react/issues/4193) [#4154](https://github.com/patternfly/patternfly-react/issues/4154) [#4192](https://github.com/patternfly/patternfly-react/issues/4192) [#4190](https://github.com/patternfly/patternfly-react/issues/4190) [#4199](https://github.com/patternfly/patternfly-react/issues/4199) [#4133](https://github.com/patternfly/patternfly-react/issues/4133) [#4165](https://github.com/patternfly/patternfly-react/issues/4165) [#4208](https://github.com/patternfly/patternfly-react/issues/4208) [#4212](https://github.com/patternfly/patternfly-react/issues/4212) [#4130](https://github.com/patternfly/patternfly-react/issues/4130) [#4219](https://github.com/patternfly/patternfly-react/issues/4219) [#4166](https://github.com/patternfly/patternfly-react/issues/4166) [#4202](https://github.com/patternfly/patternfly-react/issues/4202) [#4216](https://github.com/patternfly/patternfly-react/issues/4216) [#4225](https://github.com/patternfly/patternfly-react/issues/4225) [#4221](https://github.com/patternfly/patternfly-react/issues/4221) [#4146](https://github.com/patternfly/patternfly-react/issues/4146) [#3951](https://github.com/patternfly/patternfly-react/issues/3951) [#3681](https://github.com/patternfly/patternfly-react/issues/3681) [#4243](https://github.com/patternfly/patternfly-react/issues/4243) [#4220](https://github.com/patternfly/patternfly-react/issues/4220) [#4153](https://github.com/patternfly/patternfly-react/issues/4153) [#4209](https://github.com/patternfly/patternfly-react/issues/4209) [#4249](https://github.com/patternfly/patternfly-react/issues/4249) [#4239](https://github.com/patternfly/patternfly-react/issues/4239) [#4247](https://github.com/patternfly/patternfly-react/issues/4247) [#4246](https://github.com/patternfly/patternfly-react/issues/4246) [#3684](https://github.com/patternfly/patternfly-react/issues/3684) [#4223](https://github.com/patternfly/patternfly-react/issues/4223) [#4195](https://github.com/patternfly/patternfly-react/issues/4195) [#4254](https://github.com/patternfly/patternfly-react/issues/4254) - - - - - -## [0.4.2](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@0.4.1...eslint-plugin-patternfly-react@0.4.2) (2020-05-05) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## [0.4.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@0.4.0...eslint-plugin-patternfly-react@0.4.1) (2020-03-02) - - -### Bug Fixes - -* **eslint:** fix eslint recommendations ([#3858](https://github.com/patternfly/patternfly-react/issues/3858)) ([09cd0b8](https://github.com/patternfly/patternfly-react/commit/09cd0b8ca1495a1c4f9c870259b250ad3450e6ec)) - - - - - -# [0.4.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@0.3.0...eslint-plugin-patternfly-react@0.4.0) (2020-02-03) - - -### Features - -* **eslint:** add react-hooks to eslint-plugin-patternfly-react ([#3636](https://github.com/patternfly/patternfly-react/issues/3636)) ([fb62dc1](https://github.com/patternfly/patternfly-react/commit/fb62dc11fea53222334d8708f0ff41db8eadaafa)) - - - - - -# [0.3.0](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@0.2.3...eslint-plugin-patternfly-react@0.3.0) (2019-10-16) - - -### Features - -* **eslint:** add eslint-plugin-react-hooks ([#3083](https://github.com/patternfly/patternfly-react/issues/3083)) ([c47f143](https://github.com/patternfly/patternfly-react/commit/c47f143)) - - - - - -## 0.2.3 (2019-04-15) - - -### Bug Fixes - -* Update React with changes from core ([#1703](https://github.com/patternfly/patternfly-react/issues/1703)) ([a219cae](https://github.com/patternfly/patternfly-react/commit/a219cae)), closes [#1680](https://github.com/patternfly/patternfly-react/issues/1680) [#1684](https://github.com/patternfly/patternfly-react/issues/1684) [#1684](https://github.com/patternfly/patternfly-react/issues/1684) - - - - - -## 0.2.2 (2019-03-04) - -**Note:** Version bump only for package eslint-plugin-patternfly-react - - - - - -## [0.2.1](https://github.com/patternfly/patternfly-react/compare/eslint-plugin-patternfly-react@0.2.0...eslint-plugin-patternfly-react@0.2.1) (2019-01-18) - -**Note:** Version bump only for package eslint-plugin-patternfly-react +## 4.80.5-alpha.0 (2023-02-10) diff --git a/packages/eslint-plugin-patternfly-react/README.md b/packages/eslint-plugin-patternfly-react/README.md index f60a9ae6b58..33f126e2893 100644 --- a/packages/eslint-plugin-patternfly-react/README.md +++ b/packages/eslint-plugin-patternfly-react/README.md @@ -4,13 +4,13 @@ This package provides PatternFly React all ESLint rules bundled together for use ### Installing -``` +```sh yarn add -D eslint-plugin-patternfly-react ``` or -``` +```sh npm install eslint-plugin-patternfly-react --save-dev ``` @@ -34,17 +34,3 @@ module.exports = { extends: ['plugin:patternfly-react/recommended'] }; ``` - -### Building - -``` -yarn build -``` - -Note the build scripts for this are located in the root package.json under `yarn build`. - -### Publishing - -``` -yarn publish -``` diff --git a/packages/eslint-plugin-patternfly-react/lib/config/recommended.js b/packages/eslint-plugin-patternfly-react/lib/config/recommended.js index 5e7009ce162..e415e98ac69 100644 --- a/packages/eslint-plugin-patternfly-react/lib/config/recommended.js +++ b/packages/eslint-plugin-patternfly-react/lib/config/recommended.js @@ -1,4 +1,5 @@ module.exports = { + plugins: ['patternfly-react'], rules: { 'patternfly-react/import-default-name': [ 'error', @@ -6,67 +7,6 @@ module.exports = { classnames: 'classNames', 'prop-types': 'PropTypes' } - ], - 'jsx-a11y/heading-has-content': 'off', - 'jsx-a11y/anchor-has-content': 'off', - 'jsx-a11y/anchor-is-valid': 'off', - 'jsx-a11y/label-has-for': 'off', - 'jsx-a11y/click-events-have-key-events': 'off', - 'jsx-a11y/no-static-element-interactions': 'off', - 'jsx-a11y/no-noninteractive-element-interactions': 'off', - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true - } - ], - 'import/no-named-default': 'off', - 'import/prefer-default-export': 'off', - 'no-alert': 'off', - 'no-param-reassign': 'off', - 'no-plusplus': 'off', - 'no-prototype-builtins': 'off', - 'no-restricted-syntax': 'off', - 'no-underscore-dangle': 'off', - 'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }], - 'no-unused-vars': [ - 'error', - { - vars: 'all', - args: 'none', - ignoreRestSiblings: true - } - ], - 'no-use-before-define': 'off', - 'prettier/prettier': [ - 'error', - { semi: true, singleQuote: true, tabWidth: 2, trailingComma: 'none', useTabs: false, printWidth: 120 } - ], - 'react/no-array-index-key': 'off', - 'react/forbid-prop-types': 'off', - 'react/jsx-filename-extension': 'off', - 'react/jsx-uses-vars': 'error', - 'react/no-danger': 'off', - 'react/sort-comp': 'off', - 'react-hooks/rules-of-hooks': 'error', - 'react-hooks/exhaustive-deps': 'warn' - }, - extends: [ - 'standard', - 'standard-react', - 'standard-jsx', - 'airbnb', - 'plugin:jest/recommended', - 'prettier', - 'prettier/react', - 'plugin:react-hooks/recommended' - ], - env: { - es6: true, - browser: true, - node: true, - jest: true - }, - plugins: ['prettier', 'jest', 'react', 'react-hooks', 'patternfly-react'], - parser: 'babel-eslint' + ] + } }; diff --git a/packages/eslint-plugin-patternfly-react/lib/rules/import-default-name.js b/packages/eslint-plugin-patternfly-react/lib/rules/import-default-name.js index cf07f26733d..e0df907dcc2 100644 --- a/packages/eslint-plugin-patternfly-react/lib/rules/import-default-name.js +++ b/packages/eslint-plugin-patternfly-react/lib/rules/import-default-name.js @@ -15,10 +15,11 @@ module.exports = { ] }, create(context) { + const sourceCode = context.sourceCode ?? context.getSourceCode(); const [importMap = {}] = context.options; return { ImportDeclaration(node) { - const defaultImport = node.specifiers.find(spec => spec.type === 'ImportDefaultSpecifier'); + const defaultImport = node.specifiers.find((spec) => spec.type === 'ImportDefaultSpecifier'); if (!defaultImport) { return; } @@ -33,9 +34,11 @@ module.exports = { received: receivedName }, fix(fixer) { - const [varDecl] = context.getDeclaredVariables(node); + const [varDecl] = sourceCode.getDeclaredVariables + ? sourceCode.getDeclaredVariables(node, fixer) + : context.getDeclaredVariables(); return [ - ...varDecl.references.map(ref => fixer.replaceText(ref.identifier, expectedName)), + ...varDecl.references.map((ref) => fixer.replaceText(ref.identifier, expectedName)), fixer.replaceText(defaultImport, expectedName) ]; } diff --git a/packages/eslint-plugin-patternfly-react/lib/rules/import-tokens-icons.js b/packages/eslint-plugin-patternfly-react/lib/rules/import-tokens-icons.js index b15e733481f..911876d2ac3 100644 --- a/packages/eslint-plugin-patternfly-react/lib/rules/import-tokens-icons.js +++ b/packages/eslint-plugin-patternfly-react/lib/rules/import-tokens-icons.js @@ -12,7 +12,7 @@ function makeImport(specifier, moduleName) { res += '/dist/esm'; if (moduleName.includes('icon')) { res += '/icons/'; - res += specifier.imported.name.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`).replace(/^-/, ''); + res += specifier.imported.name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`).replace(/^-/, ''); } else { res += `/${specifier.imported.name}`; } @@ -42,7 +42,7 @@ module.exports = { ImportDeclaration(node) { if (/@patternfly\/react-(tokens|icons)(\/dist\/(js|esm))?/.test(node.source.value)) { const esmSpecifiers = node.specifiers.filter( - specifier => + (specifier) => specifier.type === 'ImportSpecifier' && !( node.source.value.startsWith('@patternfly/react-icons') && @@ -56,7 +56,7 @@ module.exports = { fix(fixer) { return fixer.replaceText( node, - esmSpecifiers.map(spec => makeImport(spec, node.source.value)).join('\n') + esmSpecifiers.map((spec) => makeImport(spec, node.source.value)).join('\n') ); } }); diff --git a/packages/eslint-plugin-patternfly-react/lib/rules/no-anonymous-functions.js b/packages/eslint-plugin-patternfly-react/lib/rules/no-anonymous-functions.js index f103815a8c9..404922593c6 100644 --- a/packages/eslint-plugin-patternfly-react/lib/rules/no-anonymous-functions.js +++ b/packages/eslint-plugin-patternfly-react/lib/rules/no-anonymous-functions.js @@ -2,8 +2,7 @@ module.exports = { meta: { docs: { - description: - "Don't use arrow functions or classes without a displayName so Enzyme and React devtools show component name", + description: "Don't use arrow functions or classes without a displayName so React devtools show component name", category: 'Possible Errors', recommended: false }, @@ -17,6 +16,7 @@ module.exports = { ] }, create(context) { + const sourceCode = context.sourceCode ?? context.getSourceCode(); return { ExportNamedDeclaration(node) { if (!node.declaration) { @@ -40,12 +40,11 @@ module.exports = { typeAnnotation.typeAnnotation.typeName.left.name === 'React' && ['FunctionComponent', 'FC', 'SFC'].includes(typeAnnotation.typeAnnotation.typeName.right.name) ) { - const displayNameNode = context - .getSourceCode() - .ast.body.filter(n => n.type === 'ExpressionStatement') - .filter(n => n.expression.left) + const displayNameNode = sourceCode.ast.body + .filter((n) => n.type === 'ExpressionStatement') + .filter((n) => n.expression.left) .find( - n => n.expression.left.object.name === displayName && n.expression.left.property.name === 'displayName' + (n) => n.expression.left.object.name === displayName && n.expression.left.property.name === 'displayName' ); if (!displayNameNode) { context.report({ @@ -65,7 +64,7 @@ module.exports = { declaration.superClass.property.name === 'Component' ) { const classBody = declaration.body.body; - const displayNameNode = classBody.find(n => n.type === 'ClassProperty' && n.key.name === 'displayName'); + const displayNameNode = classBody.find((n) => n.type === 'ClassProperty' && n.key.name === 'displayName'); if (!displayNameNode) { context.report({ node, diff --git a/packages/eslint-plugin-patternfly-react/package.json b/packages/eslint-plugin-patternfly-react/package.json index 4dd35b6a11c..9ef256e50d6 100644 --- a/packages/eslint-plugin-patternfly-react/package.json +++ b/packages/eslint-plugin-patternfly-react/package.json @@ -1,15 +1,18 @@ { "name": "eslint-plugin-patternfly-react", - "version": "4.27.0", - "private": false, - "main": "./lib/index.js", + "version": "6.5.0", + "type": "commonjs", + "exports": { + ".": "./lib/index.js" + }, "license": "MIT", "publishConfig": { - "access": "public" + "access": "public", + "tag": "prerelease" }, "repository": { "type": "git", - "url": "https://github.com/patternfly/patternfly-react.git" + "url": "git+https://github.com/patternfly/patternfly-react.git" }, "author": "Red Hat", "keywords": [ @@ -20,26 +23,8 @@ "bugs": { "url": "https://github.com/patternfly/patternfly-react/issues" }, - "homepage": "https://github.com/patternfly/patternfly-react/blob/main/packages/eslint-plugin/README.md", - "dependencies": { - "babel-eslint": "^9.0.0", - "eslint-config-airbnb": "^16.1.0", - "eslint-config-prettier": "^2.9.0", - "eslint-config-standard": "^11.0.0", - "eslint-config-standard-jsx": "^5.0.0", - "eslint-config-standard-react": "^6.0.0", - "eslint-plugin-import": "^2.13.0", - "eslint-plugin-jest": "^21.15.0", - "eslint-plugin-jsx-a11y": "^6.0.3", - "eslint-plugin-node": "^6.0.1", - "eslint-plugin-prettier": "^2.6.0", - "eslint-plugin-promise": "^3.7.0", - "eslint-plugin-react": "^7.7.0", - "eslint-plugin-react-hooks": "^4.1.2", - "eslint-plugin-rulesdir": "^0.1.0", - "eslint-plugin-standard": "^3.0.1" - }, + "homepage": "https://github.com/patternfly/patternfly-react/blob/main/packages/eslint-plugin-patternfly-react/README.md", "peerDependencies": { - "eslint": ">=5" + "eslint": ">=9.32.0" } } diff --git a/packages/react-catalog-view-extension/CHANGELOG.md b/packages/react-catalog-view-extension/CHANGELOG.md deleted file mode 100644 index 6b0b959dccc..00000000000 --- a/packages/react-catalog-view-extension/CHANGELOG.md +++ /dev/null @@ -1,6203 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# 4.39.0 (2022-01-14) - - -### Features - -* **DescriptionList:** add option to fill columns first ([#6736](https://github.com/patternfly/patternfly-react/issues/6736)) ([c955c29](https://github.com/patternfly/patternfly-react/commit/c955c2917dbc4b85ce58fac4f93845c429186e1b)) - - - - - -## 4.38.2 (2022-01-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.38.1 (2022-01-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.38.0 (2022-01-12) - - -### Features - -* **expandable-section:** added indented variation ([#6763](https://github.com/patternfly/patternfly-react/issues/6763)) ([703b922](https://github.com/patternfly/patternfly-react/commit/703b9224e43bedd5b37ec41d8f26f2939836d610)) - - - - - -## 4.37.1 (2022-01-11) - - -### Bug Fixes - -* **Select:** update typeahead Select children when any option attribute changes ([#6747](https://github.com/patternfly/patternfly-react/issues/6747)) ([1e03f3c](https://github.com/patternfly/patternfly-react/commit/1e03f3c6d0a7c507e33398c98863e40bb2233a62)) - - - - - -# 4.37.0 (2022-01-11) - - -### Features - -* **ToggleGroup:** support disabling all items under the parent ([#6700](https://github.com/patternfly/patternfly-react/issues/6700)) ([a60c8f3](https://github.com/patternfly/patternfly-react/commit/a60c8f3485546c797750451714a70b7e84a4ba0f)) - - - - - -## 4.36.1 (2022-01-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.36.0 (2022-01-11) - - -### Features - -* **Table:** update clickable area for checks/radios ([#6754](https://github.com/patternfly/patternfly-react/issues/6754)) ([c4f3c2d](https://github.com/patternfly/patternfly-react/commit/c4f3c2d7f515e3d6ad73d8b52238ca426281469a)) - - - - - -## 4.35.2 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.35.1 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.35.0 (2022-01-10) - - -### Features - -* **Dropdown:** add plain-text variant support ([#6721](https://github.com/patternfly/patternfly-react/issues/6721)) ([e5000e3](https://github.com/patternfly/patternfly-react/commit/e5000e36194e36b9c6ae49efdb0a513125efcb70)) - - - - - -## 4.34.11 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.34.10 (2022-01-10) - - -### Bug Fixes - -* **Tabs:** allow href navigation from tabs ([#6755](https://github.com/patternfly/patternfly-react/issues/6755)) ([290d89a](https://github.com/patternfly/patternfly-react/commit/290d89aed2dd4517db9859cc80ef2745cb8a779b)) - - - - - -## 4.34.9 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.34.8 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.34.7 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.34.6 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.34.5 (2022-01-07) - - -### Bug Fixes - -* **jumplinks:** Updated JumpLinks demo to allow for horizontal display ([#6731](https://github.com/patternfly/patternfly-react/issues/6731)) ([f37b934](https://github.com/patternfly/patternfly-react/commit/f37b9342e678da247056c73767d5d40ff5435bda)) - - - - - -## 4.34.4 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.34.3 (2022-01-06) - - -### Bug Fixes - -* **TopologyControlBar:** Update screen reader className to latest ([#6739](https://github.com/patternfly/patternfly-react/issues/6739)) ([ed9da57](https://github.com/patternfly/patternfly-react/commit/ed9da575fddf9fe7af8a891972f7a66520785411)) - - - - - -## 4.34.2 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.34.1 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.34.0 (2022-01-05) - - -### Features - -* **Table:** allow a generic to be passed for cell props ([#6691](https://github.com/patternfly/patternfly-react/issues/6691)) ([e22c7be](https://github.com/patternfly/patternfly-react/commit/e22c7bebf630b7cd71e4dc434c593b69fa2fb2c8)) - - - - - -## 4.33.3 (2022-01-04) - - -### Bug Fixes - -* **docs:** fix broken theme-patternfly-org link ([#6726](https://github.com/patternfly/patternfly-react/issues/6726)) ([4ba15e9](https://github.com/patternfly/patternfly-react/commit/4ba15e9d9611afbb80d995e4d63f5478c4212a9e)) - - - - - -## 4.33.2 (2022-01-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.33.1 (2022-01-04) - - -### Bug Fixes - -* **OverflowMenu:** pass HTMLDivElements props to group and control divs ([#6674](https://github.com/patternfly/patternfly-react/issues/6674)) ([e6d0d64](https://github.com/patternfly/patternfly-react/commit/e6d0d6406a07de04f4b232ca9a21247c0e9746c0)) - - - - - -# 4.33.0 (2021-12-22) - - -### Features - -* **Toolbar:** support customizing text in ToolbarChipGroupContent ([#6694](https://github.com/patternfly/patternfly-react/issues/6694)) ([24266ad](https://github.com/patternfly/patternfly-react/commit/24266adf569c027574abd1503b5e46974220349a)) - - - - - -## 4.32.5 (2021-12-16) - - -### Bug Fixes - -* **LogViewer:** fix the issue that scrollbar could compress the content of the logs ([#6702](https://github.com/patternfly/patternfly-react/issues/6702)) ([11aab1f](https://github.com/patternfly/patternfly-react/commit/11aab1f71a1aa9959cf14b887ab55b845a794a00)) - - - - - -## 4.32.4 (2021-12-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.32.3 (2021-12-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.32.2 (2021-12-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.32.1 (2021-12-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.32.0 (2021-12-09) - - -### Features - -* **Popover:** add composable header and alert variants ([#6664](https://github.com/patternfly/patternfly-react/issues/6664)) ([9028e8b](https://github.com/patternfly/patternfly-react/commit/9028e8ba5d674bde6a7e29532f7926e200dd632a)) - - - - - -## 4.31.1 (2021-12-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.31.0 (2021-12-08) - - -### Features - -* **DualListSelector:** add composable tree example ([#6652](https://github.com/patternfly/patternfly-react/issues/6652)) ([5fe977b](https://github.com/patternfly/patternfly-react/commit/5fe977becb5dea615724abf846f315e50931c188)) - - - - - -## 4.30.1 (2021-12-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.30.0 (2021-12-06) - - -### Features - -* **Card:** Add disabled card and clean up props ([#6659](https://github.com/patternfly/patternfly-react/issues/6659)) ([86f225a](https://github.com/patternfly/patternfly-react/commit/86f225ab2e02d617e2d380c4a7f7593037c50e84)) - - - - - -# 4.29.0 (2021-12-06) - - -### Features - -* **MenuToggle:** add plain with text variant ([#6627](https://github.com/patternfly/patternfly-react/issues/6627)) ([1f4ca5e](https://github.com/patternfly/patternfly-react/commit/1f4ca5e36d7077da3ff3e6918874048c784216e0)) - - - - - -# 4.28.0 (2021-12-06) - - -### Features - -* **Dropdown:** add toggle variants ([#6651](https://github.com/patternfly/patternfly-react/issues/6651)) ([6414309](https://github.com/patternfly/patternfly-react/commit/64143094aec86aed86adb320e059d987af4f5f24)) - - - - - -## 4.27.1 (2021-12-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.27.0 (2021-12-03) - - -### Features - -* **Select:** add ability to persist filtered children state ([#6670](https://github.com/patternfly/patternfly-react/issues/6670)) ([f618577](https://github.com/patternfly/patternfly-react/commit/f618577582e389409978bd1d6512ca0cf5d855cf)) - - - - - -## 4.26.17 (2021-12-03) - - -### Bug Fixes - -* **Slider:** fixed examples with custom steps and input ([#6662](https://github.com/patternfly/patternfly-react/issues/6662)) ([b4cab38](https://github.com/patternfly/patternfly-react/commit/b4cab38a2492564bf91e3711ce322951bcc6a051)) - - - - - -## 4.26.16 (2021-12-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.15 (2021-12-02) - - -### Bug Fixes - -* **Tile:** fix selecting tile in tile demo ([#6653](https://github.com/patternfly/patternfly-react/issues/6653)) ([e12e44d](https://github.com/patternfly/patternfly-react/commit/e12e44d4b623de305b7df04174144a9496d282a7)) - - - - - -## 4.26.14 (2021-12-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.13 (2021-11-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.12 (2021-11-30) - - -### Bug Fixes - -* **action-list:** added support for classname ([#6647](https://github.com/patternfly/patternfly-react/issues/6647)) ([dd3d2ce](https://github.com/patternfly/patternfly-react/commit/dd3d2ce32b4d3e7562faf465abdc508e17f097d9)) - - - - - -## 4.26.11 (2021-11-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.10 (2021-11-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.9 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.8 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.7 (2021-11-18) - - -### Bug Fixes - -* **pagination:** updated toggleTemplate prop description to include ofWord prop ([#6622](https://github.com/patternfly/patternfly-react/issues/6622)) ([26733a6](https://github.com/patternfly/patternfly-react/commit/26733a6a256ad0e873afbc268a712027470fdeaa)) - - - - - -## 4.26.6 (2021-11-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.5 (2021-11-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.4 (2021-11-15) - - -### Bug Fixes - -* **FileUpload:** Downgrade react-dropzone back to 9.0.0 to avoid a breaking type change, fix behavior regressions ([#6610](https://github.com/patternfly/patternfly-react/issues/6610)) ([574bf4f](https://github.com/patternfly/patternfly-react/commit/574bf4ff3ccf7f67ce750bc48067eaf826e99990)) - - - - - -## 4.26.3 (2021-11-15) - - -### Bug Fixes - -* **Menu:** allow maxMenuHeight with Scrollabe ([#6608](https://github.com/patternfly/patternfly-react/issues/6608)) ([8c1f12c](https://github.com/patternfly/patternfly-react/commit/8c1f12c2b0e86bbc5ba1071db3ebf29fee7421a0)) - - - - - -## 4.26.2 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.26.1 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.26.0 (2021-11-12) - - -### Features - -* **card:** added hoverable/selectable/selected-raised variant ([#6565](https://github.com/patternfly/patternfly-react/issues/6565)) ([8c60568](https://github.com/patternfly/patternfly-react/commit/8c60568ba4fa18398fed636710e222ce506de82c)) - - - - - -## 4.25.2 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.25.1 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.25.0 (2021-11-11) - - -### Features - -* **ComposableTable:** add sticky columns and nested headers ([#6538](https://github.com/patternfly/patternfly-react/issues/6538)) ([f11245b](https://github.com/patternfly/patternfly-react/commit/f11245bfccc8c6c02a9d5545a69ed533743cc552)) - - - - - -# 4.24.0 (2021-11-11) - - -### Features - -* **contextselector:** added support for context selector items as links ([#6554](https://github.com/patternfly/patternfly-react/issues/6554)) ([c465388](https://github.com/patternfly/patternfly-react/commit/c4653881eee0cd8ec8e3a7125bbef0bded9f2de0)) - - - - - -# 4.23.0 (2021-11-11) - - -### Features - -* **Navigation:** Added exemple with third level ([#6564](https://github.com/patternfly/patternfly-react/issues/6564)) ([c30da53](https://github.com/patternfly/patternfly-react/commit/c30da532855118f705c8cfc87c545bb1eea11ebb)) - - - - - -# 4.22.0 (2021-11-11) - - -### Features - -* enhance type correctness of CodeEditor ([#6579](https://github.com/patternfly/patternfly-react/issues/6579)) ([e1ad65c](https://github.com/patternfly/patternfly-react/commit/e1ad65c225968d5a9c74019d19e4a3c5e2666926)) - - - - - -## 4.21.4 (2021-11-10) - - -### Bug Fixes - -* **jumplinks:** fixed to always set clicked item as active ([#6542](https://github.com/patternfly/patternfly-react/issues/6542)) ([845c98f](https://github.com/patternfly/patternfly-react/commit/845c98f5f3df8aa9b6acc190707c5f1d7bf3ca38)) - - - - - -## 4.21.3 (2021-11-10) - - -### Bug Fixes - -* **Menu:** stop passing disableHover to DrilldownMenu DOM ([#6571](https://github.com/patternfly/patternfly-react/issues/6571)) ([63dcf25](https://github.com/patternfly/patternfly-react/commit/63dcf256723848ff3789828fc0a5f86d5009fc87)) - - - - - -## 4.21.2 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.21.1 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.21.0 (2021-11-09) - - -### Features - -* **Table:** set default sort direction ([#6544](https://github.com/patternfly/patternfly-react/issues/6544)) ([9ee4942](https://github.com/patternfly/patternfly-react/commit/9ee49428c8e1041721f2a09f8176a5aba3335049)) - - - - - -## 4.20.4 (2021-11-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.20.3 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.20.2 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.20.1 (2021-11-08) - - -### Bug Fixes - -* **acccessconsoles:** use object type Select options values in order to not mix displayed text with option keys ([#6496](https://github.com/patternfly/patternfly-react/issues/6496)) ([975c8e1](https://github.com/patternfly/patternfly-react/commit/975c8e14d7ea8c53eb4048ea6ef73e804b3ad2be)) - - - - - -# 4.20.0 (2021-11-04) - - -### Features - -* **log-viewer:** support ANSI color ([#6519](https://github.com/patternfly/patternfly-react/issues/6519)) ([936a699](https://github.com/patternfly/patternfly-react/commit/936a699b0514a492d3c40be08932fb7bab275cce)) - - - - - -## 4.19.11 (2021-11-01) - - -### Bug Fixes - -* **AboutModal:** allow to disable FocusTrap ([#6509](https://github.com/patternfly/patternfly-react/issues/6509)) ([72536e1](https://github.com/patternfly/patternfly-react/commit/72536e1f73641ff3f19f865f08dbb41ad0ee7b9f)) - - - - - -## 4.19.10 (2021-10-29) - - -### Bug Fixes - -* **Banner:** forward props ([#6511](https://github.com/patternfly/patternfly-react/issues/6511)) ([e36c890](https://github.com/patternfly/patternfly-react/commit/e36c89077afa82340994c0e3c0fc929e601e01bc)) - - - - - -## 4.19.9 (2021-10-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.19.8 (2021-10-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.19.7 (2021-10-27) - - -### Bug Fixes - -* change transformer cjs package to private ([#6515](https://github.com/patternfly/patternfly-react/issues/6515)) ([efcb357](https://github.com/patternfly/patternfly-react/commit/efcb3573b71541328ce2b16caa80ce33b2a62131)) - - - - - -## 4.19.6 (2021-10-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.19.5 (2021-10-26) - - -### Bug Fixes - -* **tokens:** added check for no matching var to avoid infinite loop ([#6502](https://github.com/patternfly/patternfly-react/issues/6502)) ([99605c2](https://github.com/patternfly/patternfly-react/commit/99605c213f12490d0abe75910e05c3e6da26a1f3)) - - - - - -## 4.19.4 (2021-10-26) - - -### Bug Fixes - -* add transformer package ([#6507](https://github.com/patternfly/patternfly-react/issues/6507)) ([daffd28](https://github.com/patternfly/patternfly-react/commit/daffd2864388abe63e625f962a8b38c2b7056209)) - - - - - -## 4.19.3 (2021-10-26) - - -### Bug Fixes - -* **transformer:** publish transformer in patternfly org ([#6506](https://github.com/patternfly/patternfly-react/issues/6506)) ([b739af3](https://github.com/patternfly/patternfly-react/commit/b739af318400b41d4e9a53bdff6232ecc176916e)) - - - - - -## 4.19.2 (2021-10-26) - - -### Bug Fixes - -* **readme:** update react-core readme ([#6505](https://github.com/patternfly/patternfly-react/issues/6505)) ([d4f9a11](https://github.com/patternfly/patternfly-react/commit/d4f9a114584eea7ab67873f199e80b348886e14b)) - - - - - -## 4.19.1 (2021-10-26) - - -### Bug Fixes - -* **DualListSelector:** account for duplicate folders ([#6499](https://github.com/patternfly/patternfly-react/issues/6499)) ([e531e68](https://github.com/patternfly/patternfly-react/commit/e531e68e7adc58459b3630f5c915ed69e3021012)) - - - - - -# 4.19.0 (2021-10-26) - - -### Features - -* **toolbar:** add sticky top modifier to toolbar ([#6447](https://github.com/patternfly/patternfly-react/issues/6447)) ([fe7605a](https://github.com/patternfly/patternfly-react/commit/fe7605a67428b43ec00b3cb2117270296576737c)) - - - - - -## 4.18.1 (2021-10-26) - - -### Bug Fixes - -* **types:** SelectOptionProp made optional ([#6503](https://github.com/patternfly/patternfly-react/issues/6503)) ([716ac80](https://github.com/patternfly/patternfly-react/commit/716ac80e2414507d589ee3002fc0cea0068ae59c)) - - - - - -# 4.18.0 (2021-10-26) - - -### Features - -* **TextInputGroup:** add text input group ([#6482](https://github.com/patternfly/patternfly-react/issues/6482)) ([a02fd4f](https://github.com/patternfly/patternfly-react/commit/a02fd4fe3345245b2252ee5a261f5b1460490642)), closes [patternfly/patternfly-react#6409](https://github.com/patternfly/patternfly-react/issues/6409) - - - - - -## 4.17.4 (2021-10-26) - - -### Bug Fixes - -* **KebabToggle:** adds event to onToggle definition ([#6490](https://github.com/patternfly/patternfly-react/issues/6490)) ([0441575](https://github.com/patternfly/patternfly-react/commit/04415757917062aa13c06b34bd94ef38c2334088)) - - - - - -## 4.17.3 (2021-10-26) - - -### Bug Fixes - -* **Modal:** test clean up ([#6489](https://github.com/patternfly/patternfly-react/issues/6489)) ([c8eaa7c](https://github.com/patternfly/patternfly-react/commit/c8eaa7c838fbedb98ea0f38e4f535488040a72e2)) - - - - - -## 4.17.2 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.17.1 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.17.0 (2021-10-25) - - -### Features - -* **Tabs:** Added support for tab content body with padding, added tabs open and tab secondary tabs demos ([#6484](https://github.com/patternfly/patternfly-react/issues/6484)) ([0ccbe9d](https://github.com/patternfly/patternfly-react/commit/0ccbe9d1e6e0dac0730466c92a90fe2cd9f6560d)) - - - - - -## 4.16.1 (2021-10-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 4.16.0 (2021-10-21) - - -### Features - -* **label:** added compact label, updated horizontal grid card demo ([#6448](https://github.com/patternfly/patternfly-react/issues/6448)) ([89e0431](https://github.com/patternfly/patternfly-react/commit/89e04317924282140606d45f2292aa3f658b4b6c)) - - - - - -## 4.15.1 (2021-10-21) - - -### Bug Fixes - -* **DescriptionListGroup:** forward props to DOM ([#6466](https://github.com/patternfly/patternfly-react/issues/6466)) ([b78e2aa](https://github.com/patternfly/patternfly-react/commit/b78e2aa9c0360ce8418f6e7b55274ea1a50de518)) - - - - - -# 4.15.0 (2021-10-20) - - -### Features - -* **Progress:** allow node titles ([#6470](https://github.com/patternfly/patternfly-react/issues/6470)) ([46d5252](https://github.com/patternfly/patternfly-react/commit/46d52523ad5111bb11729c2750abe9aeb35d9326)) - - - - - -# 4.14.0 (2021-10-20) - - -### Features - -* **DualListSelector:** add disabled flag ([#6442](https://github.com/patternfly/patternfly-react/issues/6442)) ([85e1314](https://github.com/patternfly/patternfly-react/commit/85e131435be12c2df79336e9fa56987ed3717417)) - - - - - -## 4.13.23 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## 4.13.22 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.20...@patternfly/react-catalog-view-extension@4.13.21) (2021-10-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.19...@patternfly/react-catalog-view-extension@4.13.20) (2021-10-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.18...@patternfly/react-catalog-view-extension@4.13.19) (2021-10-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.17...@patternfly/react-catalog-view-extension@4.13.18) (2021-10-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.16...@patternfly/react-catalog-view-extension@4.13.17) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.15...@patternfly/react-catalog-view-extension@4.13.16) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.14...@patternfly/react-catalog-view-extension@4.13.15) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.13...@patternfly/react-catalog-view-extension@4.13.14) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.12...@patternfly/react-catalog-view-extension@4.13.13) (2021-10-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.11...@patternfly/react-catalog-view-extension@4.13.12) (2021-10-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.10...@patternfly/react-catalog-view-extension@4.13.11) (2021-10-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.9...@patternfly/react-catalog-view-extension@4.13.10) (2021-10-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.8...@patternfly/react-catalog-view-extension@4.13.9) (2021-10-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.7...@patternfly/react-catalog-view-extension@4.13.8) (2021-10-06) - - -### Bug Fixes - -* **catalog, umd:** remove node-sass to allow building on node16 ([#6398](https://github.com/patternfly/patternfly-react/issues/6398)) ([212611a](https://github.com/patternfly/patternfly-react/commit/212611aae49d30385b500b5299be2975900ec22c)) - - - - - -## [4.13.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.6...@patternfly/react-catalog-view-extension@4.13.7) (2021-10-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.5...@patternfly/react-catalog-view-extension@4.13.6) (2021-10-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.4...@patternfly/react-catalog-view-extension@4.13.5) (2021-10-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.3...@patternfly/react-catalog-view-extension@4.13.4) (2021-10-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.2...@patternfly/react-catalog-view-extension@4.13.3) (2021-10-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.1...@patternfly/react-catalog-view-extension@4.13.2) (2021-10-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.13.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.13.0...@patternfly/react-catalog-view-extension@4.13.1) (2021-09-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.13.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.79...@patternfly/react-catalog-view-extension@4.13.0) (2021-09-29) - - -### Features - -* **JumpLinks:** Added toggle text ([#6347](https://github.com/patternfly/patternfly-react/issues/6347)) ([36042f6](https://github.com/patternfly/patternfly-react/commit/36042f679880f819afd26618797167a42f5fe901)) - - - - - -## [4.12.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.78...@patternfly/react-catalog-view-extension@4.12.79) (2021-09-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.77...@patternfly/react-catalog-view-extension@4.12.78) (2021-09-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.76...@patternfly/react-catalog-view-extension@4.12.77) (2021-09-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.75...@patternfly/react-catalog-view-extension@4.12.76) (2021-09-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.74...@patternfly/react-catalog-view-extension@4.12.75) (2021-09-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.73...@patternfly/react-catalog-view-extension@4.12.74) (2021-09-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.72...@patternfly/react-catalog-view-extension@4.12.73) (2021-09-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.71...@patternfly/react-catalog-view-extension@4.12.72) (2021-09-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.70...@patternfly/react-catalog-view-extension@4.12.71) (2021-09-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.69...@patternfly/react-catalog-view-extension@4.12.70) (2021-09-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.68...@patternfly/react-catalog-view-extension@4.12.69) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.67...@patternfly/react-catalog-view-extension@4.12.68) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.66...@patternfly/react-catalog-view-extension@4.12.67) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.65...@patternfly/react-catalog-view-extension@4.12.66) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.64...@patternfly/react-catalog-view-extension@4.12.65) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.63...@patternfly/react-catalog-view-extension@4.12.64) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.62...@patternfly/react-catalog-view-extension@4.12.63) (2021-09-10) - - -### Bug Fixes - -* **dual-list-selector:** added support for list item row, bumped core ([#6294](https://github.com/patternfly/patternfly-react/issues/6294)) ([010efb5](https://github.com/patternfly/patternfly-react/commit/010efb51c46740bd1e28866d6b956c363819b69d)) - - - - - -## [4.12.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.61...@patternfly/react-catalog-view-extension@4.12.62) (2021-09-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.60...@patternfly/react-catalog-view-extension@4.12.61) (2021-09-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.59...@patternfly/react-catalog-view-extension@4.12.60) (2021-09-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.58...@patternfly/react-catalog-view-extension@4.12.59) (2021-08-31) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.57...@patternfly/react-catalog-view-extension@4.12.58) (2021-08-31) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.56...@patternfly/react-catalog-view-extension@4.12.57) (2021-08-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.55...@patternfly/react-catalog-view-extension@4.12.56) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.54...@patternfly/react-catalog-view-extension@4.12.55) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.53...@patternfly/react-catalog-view-extension@4.12.54) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.52...@patternfly/react-catalog-view-extension@4.12.53) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.51...@patternfly/react-catalog-view-extension@4.12.52) (2021-08-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.50...@patternfly/react-catalog-view-extension@4.12.51) (2021-08-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.49...@patternfly/react-catalog-view-extension@4.12.50) (2021-08-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.48...@patternfly/react-catalog-view-extension@4.12.49) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.47...@patternfly/react-catalog-view-extension@4.12.48) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.46...@patternfly/react-catalog-view-extension@4.12.47) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.45...@patternfly/react-catalog-view-extension@4.12.46) (2021-08-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.44...@patternfly/react-catalog-view-extension@4.12.45) (2021-08-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.43...@patternfly/react-catalog-view-extension@4.12.44) (2021-08-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.42...@patternfly/react-catalog-view-extension@4.12.43) (2021-08-16) - - -### Bug Fixes - -* **VerticalTabs:** expose href to allow links ([#6072](https://github.com/patternfly/patternfly-react/issues/6072)) ([2b66bcd](https://github.com/patternfly/patternfly-react/commit/2b66bcd07d1675649c045d6cd06a99377c77fcca)) - - - - - -## [4.12.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.41...@patternfly/react-catalog-view-extension@4.12.42) (2021-08-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.40...@patternfly/react-catalog-view-extension@4.12.41) (2021-08-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.39...@patternfly/react-catalog-view-extension@4.12.40) (2021-08-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.38...@patternfly/react-catalog-view-extension@4.12.39) (2021-08-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.37...@patternfly/react-catalog-view-extension@4.12.38) (2021-08-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.36...@patternfly/react-catalog-view-extension@4.12.37) (2021-08-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.35...@patternfly/react-catalog-view-extension@4.12.36) (2021-08-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.34...@patternfly/react-catalog-view-extension@4.12.35) (2021-08-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.33...@patternfly/react-catalog-view-extension@4.12.34) (2021-08-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.32...@patternfly/react-catalog-view-extension@4.12.33) (2021-08-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.31...@patternfly/react-catalog-view-extension@4.12.32) (2021-07-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.30...@patternfly/react-catalog-view-extension@4.12.31) (2021-07-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.29...@patternfly/react-catalog-view-extension@4.12.30) (2021-07-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.28...@patternfly/react-catalog-view-extension@4.12.29) (2021-07-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.27...@patternfly/react-catalog-view-extension@4.12.28) (2021-07-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.26...@patternfly/react-catalog-view-extension@4.12.27) (2021-07-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.25...@patternfly/react-catalog-view-extension@4.12.26) (2021-07-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.24...@patternfly/react-catalog-view-extension@4.12.25) (2021-07-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.23...@patternfly/react-catalog-view-extension@4.12.24) (2021-07-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.22...@patternfly/react-catalog-view-extension@4.12.23) (2021-07-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.21...@patternfly/react-catalog-view-extension@4.12.22) (2021-07-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.20...@patternfly/react-catalog-view-extension@4.12.21) (2021-07-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.19...@patternfly/react-catalog-view-extension@4.12.20) (2021-07-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.18...@patternfly/react-catalog-view-extension@4.12.19) (2021-07-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.17...@patternfly/react-catalog-view-extension@4.12.18) (2021-07-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.16...@patternfly/react-catalog-view-extension@4.12.17) (2021-07-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.15...@patternfly/react-catalog-view-extension@4.12.16) (2021-07-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.14...@patternfly/react-catalog-view-extension@4.12.15) (2021-07-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.13...@patternfly/react-catalog-view-extension@4.12.14) (2021-07-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.12...@patternfly/react-catalog-view-extension@4.12.13) (2021-07-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.11...@patternfly/react-catalog-view-extension@4.12.12) (2021-07-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.10...@patternfly/react-catalog-view-extension@4.12.11) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.9...@patternfly/react-catalog-view-extension@4.12.10) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.8...@patternfly/react-catalog-view-extension@4.12.9) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.7...@patternfly/react-catalog-view-extension@4.12.8) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.6...@patternfly/react-catalog-view-extension@4.12.7) (2021-07-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.5...@patternfly/react-catalog-view-extension@4.12.6) (2021-07-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.4...@patternfly/react-catalog-view-extension@4.12.5) (2021-07-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.3...@patternfly/react-catalog-view-extension@4.12.4) (2021-07-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.2...@patternfly/react-catalog-view-extension@4.12.3) (2021-06-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.12.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.1...@patternfly/react-catalog-view-extension@4.12.2) (2021-06-30) - - -### Bug Fixes - -* **ci:** change master branch to main ([4ac4129](https://github.com/patternfly/patternfly-react/commit/4ac4129e8da9a37367ea7612019f8d7af1ed8836)) - - - - - -## [4.12.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.12.0...@patternfly/react-catalog-view-extension@4.12.1) (2021-06-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.12.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.56...@patternfly/react-catalog-view-extension@4.12.0) (2021-06-21) - - -### Features - -* **LogViewer:** Make logviewer responsive and change search result styling ([#5927](https://github.com/patternfly/patternfly-react/issues/5927)) ([3f6a493](https://github.com/patternfly/patternfly-react/commit/3f6a4934127d23de1baf2447003296600d9f3c5b)) - - - - - -## [4.11.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.55...@patternfly/react-catalog-view-extension@4.11.56) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.54...@patternfly/react-catalog-view-extension@4.11.55) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.53...@patternfly/react-catalog-view-extension@4.11.54) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.52...@patternfly/react-catalog-view-extension@4.11.53) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.51...@patternfly/react-catalog-view-extension@4.11.52) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.50...@patternfly/react-catalog-view-extension@4.11.51) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.49...@patternfly/react-catalog-view-extension@4.11.50) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.48...@patternfly/react-catalog-view-extension@4.11.49) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.47...@patternfly/react-catalog-view-extension@4.11.48) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.46...@patternfly/react-catalog-view-extension@4.11.47) (2021-06-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.45...@patternfly/react-catalog-view-extension@4.11.46) (2021-06-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.44...@patternfly/react-catalog-view-extension@4.11.45) (2021-06-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.43...@patternfly/react-catalog-view-extension@4.11.44) (2021-06-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.42...@patternfly/react-catalog-view-extension@4.11.43) (2021-06-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.41...@patternfly/react-catalog-view-extension@4.11.42) (2021-06-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.40...@patternfly/react-catalog-view-extension@4.11.41) (2021-06-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.39...@patternfly/react-catalog-view-extension@4.11.40) (2021-06-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.38...@patternfly/react-catalog-view-extension@4.11.39) (2021-06-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.37...@patternfly/react-catalog-view-extension@4.11.38) (2021-06-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.36...@patternfly/react-catalog-view-extension@4.11.37) (2021-06-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.35...@patternfly/react-catalog-view-extension@4.11.36) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.34...@patternfly/react-catalog-view-extension@4.11.35) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.33...@patternfly/react-catalog-view-extension@4.11.34) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.32...@patternfly/react-catalog-view-extension@4.11.33) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.31...@patternfly/react-catalog-view-extension@4.11.32) (2021-05-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.30...@patternfly/react-catalog-view-extension@4.11.31) (2021-05-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.29...@patternfly/react-catalog-view-extension@4.11.30) (2021-05-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.28...@patternfly/react-catalog-view-extension@4.11.29) (2021-05-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.27...@patternfly/react-catalog-view-extension@4.11.28) (2021-05-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.26...@patternfly/react-catalog-view-extension@4.11.27) (2021-05-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.25...@patternfly/react-catalog-view-extension@4.11.26) (2021-05-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.24...@patternfly/react-catalog-view-extension@4.11.25) (2021-05-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.23...@patternfly/react-catalog-view-extension@4.11.24) (2021-05-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.22...@patternfly/react-catalog-view-extension@4.11.23) (2021-05-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.21...@patternfly/react-catalog-view-extension@4.11.22) (2021-05-11) - - -### Bug Fixes - -* **togglegroup:** remove dividers, light variation, add compact ([#5762](https://github.com/patternfly/patternfly-react/issues/5762)) ([d5c8c31](https://github.com/patternfly/patternfly-react/commit/d5c8c31bb24f613687fcf5aa3213ee51a8007580)) - - - - - -## [4.11.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.20...@patternfly/react-catalog-view-extension@4.11.21) (2021-05-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.19...@patternfly/react-catalog-view-extension@4.11.20) (2021-05-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.18...@patternfly/react-catalog-view-extension@4.11.19) (2021-05-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.17...@patternfly/react-catalog-view-extension@4.11.18) (2021-05-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.16...@patternfly/react-catalog-view-extension@4.11.17) (2021-05-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.15...@patternfly/react-catalog-view-extension@4.11.16) (2021-05-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.14...@patternfly/react-catalog-view-extension@4.11.15) (2021-05-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.13...@patternfly/react-catalog-view-extension@4.11.14) (2021-05-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.12...@patternfly/react-catalog-view-extension@4.11.13) (2021-05-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.11...@patternfly/react-catalog-view-extension@4.11.12) (2021-05-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.10...@patternfly/react-catalog-view-extension@4.11.11) (2021-05-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.9...@patternfly/react-catalog-view-extension@4.11.10) (2021-05-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.8...@patternfly/react-catalog-view-extension@4.11.9) (2021-04-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.7...@patternfly/react-catalog-view-extension@4.11.8) (2021-04-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.6...@patternfly/react-catalog-view-extension@4.11.7) (2021-04-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.5...@patternfly/react-catalog-view-extension@4.11.6) (2021-04-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.4...@patternfly/react-catalog-view-extension@4.11.5) (2021-04-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.3...@patternfly/react-catalog-view-extension@4.11.4) (2021-04-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.2...@patternfly/react-catalog-view-extension@4.11.3) (2021-04-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.1...@patternfly/react-catalog-view-extension@4.11.2) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.11.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.11.0...@patternfly/react-catalog-view-extension@4.11.1) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.11.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.43...@patternfly/react-catalog-view-extension@4.11.0) (2021-04-16) - - -### Features - -* **Table:** Add optional icons to tree table rows, add responsive view ([#5672](https://github.com/patternfly/patternfly-react/issues/5672)) ([7ecba96](https://github.com/patternfly/patternfly-react/commit/7ecba96a191798d01c7f9209a14a04f4a658d7bb)) - - - - - -## [4.10.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.42...@patternfly/react-catalog-view-extension@4.10.43) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.41...@patternfly/react-catalog-view-extension@4.10.42) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.40...@patternfly/react-catalog-view-extension@4.10.41) (2021-04-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.39...@patternfly/react-catalog-view-extension@4.10.40) (2021-04-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.38...@patternfly/react-catalog-view-extension@4.10.39) (2021-04-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.37...@patternfly/react-catalog-view-extension@4.10.38) (2021-04-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.36...@patternfly/react-catalog-view-extension@4.10.37) (2021-04-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.35...@patternfly/react-catalog-view-extension@4.10.36) (2021-04-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.34...@patternfly/react-catalog-view-extension@4.10.35) (2021-04-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.33...@patternfly/react-catalog-view-extension@4.10.34) (2021-04-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.32...@patternfly/react-catalog-view-extension@4.10.33) (2021-04-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.31...@patternfly/react-catalog-view-extension@4.10.32) (2021-04-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.30...@patternfly/react-catalog-view-extension@4.10.31) (2021-04-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.29...@patternfly/react-catalog-view-extension@4.10.30) (2021-04-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.28...@patternfly/react-catalog-view-extension@4.10.29) (2021-04-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.27...@patternfly/react-catalog-view-extension@4.10.28) (2021-03-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.26...@patternfly/react-catalog-view-extension@4.10.27) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.25...@patternfly/react-catalog-view-extension@4.10.26) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.24...@patternfly/react-catalog-view-extension@4.10.25) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.23...@patternfly/react-catalog-view-extension@4.10.24) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.22...@patternfly/react-catalog-view-extension@4.10.23) (2021-03-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.21...@patternfly/react-catalog-view-extension@4.10.22) (2021-03-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.20...@patternfly/react-catalog-view-extension@4.10.21) (2021-03-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.19...@patternfly/react-catalog-view-extension@4.10.20) (2021-03-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.18...@patternfly/react-catalog-view-extension@4.10.19) (2021-03-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.17...@patternfly/react-catalog-view-extension@4.10.18) (2021-03-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.16...@patternfly/react-catalog-view-extension@4.10.17) (2021-03-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.15...@patternfly/react-catalog-view-extension@4.10.16) (2021-03-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.14...@patternfly/react-catalog-view-extension@4.10.15) (2021-03-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.13...@patternfly/react-catalog-view-extension@4.10.14) (2021-03-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.12...@patternfly/react-catalog-view-extension@4.10.13) (2021-03-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.11...@patternfly/react-catalog-view-extension@4.10.12) (2021-03-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.10...@patternfly/react-catalog-view-extension@4.10.11) (2021-03-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.9...@patternfly/react-catalog-view-extension@4.10.10) (2021-03-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.8...@patternfly/react-catalog-view-extension@4.10.9) (2021-03-04) - - -### Bug Fixes - -* **searchinput:** add searchInputMenuBody class ([#5518](https://github.com/patternfly/patternfly-react/issues/5518)) ([99f0512](https://github.com/patternfly/patternfly-react/commit/99f05123d28a7be887efd1921733fc2dc0bddd6d)) - - - - - -## [4.10.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.7...@patternfly/react-catalog-view-extension@4.10.8) (2021-03-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.6...@patternfly/react-catalog-view-extension@4.10.7) (2021-03-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.5...@patternfly/react-catalog-view-extension@4.10.6) (2021-03-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.4...@patternfly/react-catalog-view-extension@4.10.5) (2021-03-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.3...@patternfly/react-catalog-view-extension@4.10.4) (2021-02-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.2...@patternfly/react-catalog-view-extension@4.10.3) (2021-02-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.1...@patternfly/react-catalog-view-extension@4.10.2) (2021-02-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.10.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.10.0...@patternfly/react-catalog-view-extension@4.10.1) (2021-02-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.10.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.31...@patternfly/react-catalog-view-extension@4.10.0) (2021-02-12) - - -### Features - -* **Slider:** Added touch support ([#5453](https://github.com/patternfly/patternfly-react/issues/5453)) ([32ce723](https://github.com/patternfly/patternfly-react/commit/32ce7238d8743f6d4a5f7b128b1293e855d012ca)) - - - - - -## [4.9.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.30...@patternfly/react-catalog-view-extension@4.9.31) (2021-02-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.29...@patternfly/react-catalog-view-extension@4.9.30) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.28...@patternfly/react-catalog-view-extension@4.9.29) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.27...@patternfly/react-catalog-view-extension@4.9.28) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.26...@patternfly/react-catalog-view-extension@4.9.27) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.25...@patternfly/react-catalog-view-extension@4.9.26) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.24...@patternfly/react-catalog-view-extension@4.9.25) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.23...@patternfly/react-catalog-view-extension@4.9.24) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.22...@patternfly/react-catalog-view-extension@4.9.23) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.21...@patternfly/react-catalog-view-extension@4.9.22) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.20...@patternfly/react-catalog-view-extension@4.9.21) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.19...@patternfly/react-catalog-view-extension@4.9.20) (2021-02-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.18...@patternfly/react-catalog-view-extension@4.9.19) (2021-02-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.17...@patternfly/react-catalog-view-extension@4.9.18) (2021-02-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.16...@patternfly/react-catalog-view-extension@4.9.17) (2021-02-01) - - -### Bug Fixes - -* **Tooltip:** only add aria when tooltip is visible/in the DOM ([#5382](https://github.com/patternfly/patternfly-react/issues/5382)) ([10263d9](https://github.com/patternfly/patternfly-react/commit/10263d993ea781a1bf681816eeddce9fa7657670)) - - - - - -## [4.9.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.15...@patternfly/react-catalog-view-extension@4.9.16) (2021-02-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.14...@patternfly/react-catalog-view-extension@4.9.15) (2021-01-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.13...@patternfly/react-catalog-view-extension@4.9.14) (2021-01-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.12...@patternfly/react-catalog-view-extension@4.9.13) (2021-01-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.11...@patternfly/react-catalog-view-extension@4.9.12) (2021-01-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.10...@patternfly/react-catalog-view-extension@4.9.11) (2021-01-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.9...@patternfly/react-catalog-view-extension@4.9.10) (2021-01-22) - - -### Bug Fixes - -* **Drawer:** initial width doesn't respect min/max widths ([#5313](https://github.com/patternfly/patternfly-react/issues/5313)) ([4f199c4](https://github.com/patternfly/patternfly-react/commit/4f199c4db5c3cb493d2947d871f687cc5527517c)) - - - - - -## [4.9.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.8...@patternfly/react-catalog-view-extension@4.9.9) (2021-01-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.7...@patternfly/react-catalog-view-extension@4.9.8) (2021-01-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.6...@patternfly/react-catalog-view-extension@4.9.7) (2021-01-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.5...@patternfly/react-catalog-view-extension@4.9.6) (2021-01-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.4...@patternfly/react-catalog-view-extension@4.9.5) (2021-01-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.3...@patternfly/react-catalog-view-extension@4.9.4) (2021-01-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.2...@patternfly/react-catalog-view-extension@4.9.3) (2021-01-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.1...@patternfly/react-catalog-view-extension@4.9.2) (2021-01-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.9.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.9.0...@patternfly/react-catalog-view-extension@4.9.1) (2021-01-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.9.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.131...@patternfly/react-catalog-view-extension@4.9.0) (2021-01-06) - - -### Features - -* **packages:** use react 17 ([#5111](https://github.com/patternfly/patternfly-react/issues/5111)) ([7fbafcc](https://github.com/patternfly/patternfly-react/commit/7fbafcc947c95d2bda2f4fad8f7737cf7dd3fca6)) - - - - - -## [4.8.131](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.130...@patternfly/react-catalog-view-extension@4.8.131) (2021-01-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.130](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.129...@patternfly/react-catalog-view-extension@4.8.130) (2021-01-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.129](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.128...@patternfly/react-catalog-view-extension@4.8.129) (2021-01-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.128](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.127...@patternfly/react-catalog-view-extension@4.8.128) (2020-12-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.127](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.126...@patternfly/react-catalog-view-extension@4.8.127) (2020-12-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.126](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.125...@patternfly/react-catalog-view-extension@4.8.126) (2020-12-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.125](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.124...@patternfly/react-catalog-view-extension@4.8.125) (2020-12-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.124](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.123...@patternfly/react-catalog-view-extension@4.8.124) (2020-12-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.123](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.122...@patternfly/react-catalog-view-extension@4.8.123) (2020-12-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.122](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.121...@patternfly/react-catalog-view-extension@4.8.122) (2020-12-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.121](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.120...@patternfly/react-catalog-view-extension@4.8.121) (2020-12-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.120](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.119...@patternfly/react-catalog-view-extension@4.8.120) (2020-12-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.119](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.118...@patternfly/react-catalog-view-extension@4.8.119) (2020-12-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.118](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.117...@patternfly/react-catalog-view-extension@4.8.118) (2020-12-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.117](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.116...@patternfly/react-catalog-view-extension@4.8.117) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.116](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.115...@patternfly/react-catalog-view-extension@4.8.116) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.115](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.114...@patternfly/react-catalog-view-extension@4.8.115) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.114](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.113...@patternfly/react-catalog-view-extension@4.8.114) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.113](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.112...@patternfly/react-catalog-view-extension@4.8.113) (2020-12-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.112](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.111...@patternfly/react-catalog-view-extension@4.8.112) (2020-12-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.111](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.110...@patternfly/react-catalog-view-extension@4.8.111) (2020-12-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.110](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.109...@patternfly/react-catalog-view-extension@4.8.110) (2020-12-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.109](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.108...@patternfly/react-catalog-view-extension@4.8.109) (2020-11-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.108](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.107...@patternfly/react-catalog-view-extension@4.8.108) (2020-11-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.107](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.106...@patternfly/react-catalog-view-extension@4.8.107) (2020-11-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.106](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.105...@patternfly/react-catalog-view-extension@4.8.106) (2020-11-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.105](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.104...@patternfly/react-catalog-view-extension@4.8.105) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.104](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.103...@patternfly/react-catalog-view-extension@4.8.104) (2020-11-17) - - -### Bug Fixes - -* **FilterSidePanelCategoryItem:** fix typings ([#5145](https://github.com/patternfly/patternfly-react/issues/5145)) ([a2b55f0](https://github.com/patternfly/patternfly-react/commit/a2b55f0bff33a2afccfb66be4eedf2e5a6639420)) - - - - - -## [4.8.103](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.102...@patternfly/react-catalog-view-extension@4.8.103) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.102](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.101...@patternfly/react-catalog-view-extension@4.8.102) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.101](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.100...@patternfly/react-catalog-view-extension@4.8.101) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.100](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.99...@patternfly/react-catalog-view-extension@4.8.100) (2020-11-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.99](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.98...@patternfly/react-catalog-view-extension@4.8.99) (2020-11-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.98](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.97...@patternfly/react-catalog-view-extension@4.8.98) (2020-11-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.97](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.96...@patternfly/react-catalog-view-extension@4.8.97) (2020-11-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.96](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.95...@patternfly/react-catalog-view-extension@4.8.96) (2020-11-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.95](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.94...@patternfly/react-catalog-view-extension@4.8.95) (2020-11-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.94](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.93...@patternfly/react-catalog-view-extension@4.8.94) (2020-10-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.93](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.92...@patternfly/react-catalog-view-extension@4.8.93) (2020-10-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.92](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.91...@patternfly/react-catalog-view-extension@4.8.92) (2020-10-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.91](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.90...@patternfly/react-catalog-view-extension@4.8.91) (2020-10-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.90](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.89...@patternfly/react-catalog-view-extension@4.8.90) (2020-10-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.89](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.88...@patternfly/react-catalog-view-extension@4.8.89) (2020-10-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.88](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.87...@patternfly/react-catalog-view-extension@4.8.88) (2020-10-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.87](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.86...@patternfly/react-catalog-view-extension@4.8.87) (2020-10-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.86](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.85...@patternfly/react-catalog-view-extension@4.8.86) (2020-10-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.85](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.84...@patternfly/react-catalog-view-extension@4.8.85) (2020-10-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.84](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.83...@patternfly/react-catalog-view-extension@4.8.84) (2020-10-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.83](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.82...@patternfly/react-catalog-view-extension@4.8.83) (2020-10-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.82](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.81...@patternfly/react-catalog-view-extension@4.8.82) (2020-10-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.81](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.80...@patternfly/react-catalog-view-extension@4.8.81) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.80](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.79...@patternfly/react-catalog-view-extension@4.8.80) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.78...@patternfly/react-catalog-view-extension@4.8.79) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.77...@patternfly/react-catalog-view-extension@4.8.78) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.76...@patternfly/react-catalog-view-extension@4.8.77) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.75...@patternfly/react-catalog-view-extension@4.8.76) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.74...@patternfly/react-catalog-view-extension@4.8.75) (2020-10-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.73...@patternfly/react-catalog-view-extension@4.8.74) (2020-10-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.72...@patternfly/react-catalog-view-extension@4.8.73) (2020-10-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.71...@patternfly/react-catalog-view-extension@4.8.72) (2020-10-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.70...@patternfly/react-catalog-view-extension@4.8.71) (2020-10-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.69...@patternfly/react-catalog-view-extension@4.8.70) (2020-10-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.68...@patternfly/react-catalog-view-extension@4.8.69) (2020-10-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.67...@patternfly/react-catalog-view-extension@4.8.68) (2020-10-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.66...@patternfly/react-catalog-view-extension@4.8.67) (2020-10-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.65...@patternfly/react-catalog-view-extension@4.8.66) (2020-10-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.64...@patternfly/react-catalog-view-extension@4.8.65) (2020-10-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.63...@patternfly/react-catalog-view-extension@4.8.64) (2020-10-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.62...@patternfly/react-catalog-view-extension@4.8.63) (2020-10-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.61...@patternfly/react-catalog-view-extension@4.8.62) (2020-10-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.60...@patternfly/react-catalog-view-extension@4.8.61) (2020-10-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.59...@patternfly/react-catalog-view-extension@4.8.60) (2020-10-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.58...@patternfly/react-catalog-view-extension@4.8.59) (2020-10-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.57...@patternfly/react-catalog-view-extension@4.8.58) (2020-10-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.56...@patternfly/react-catalog-view-extension@4.8.57) (2020-10-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.55...@patternfly/react-catalog-view-extension@4.8.56) (2020-10-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.54...@patternfly/react-catalog-view-extension@4.8.55) (2020-10-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.53...@patternfly/react-catalog-view-extension@4.8.54) (2020-10-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.52...@patternfly/react-catalog-view-extension@4.8.53) (2020-10-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.51...@patternfly/react-catalog-view-extension@4.8.52) (2020-10-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.50...@patternfly/react-catalog-view-extension@4.8.51) (2020-10-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.49...@patternfly/react-catalog-view-extension@4.8.50) (2020-10-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.48...@patternfly/react-catalog-view-extension@4.8.49) (2020-10-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.47...@patternfly/react-catalog-view-extension@4.8.48) (2020-10-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.46...@patternfly/react-catalog-view-extension@4.8.47) (2020-09-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.45...@patternfly/react-catalog-view-extension@4.8.46) (2020-09-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.44...@patternfly/react-catalog-view-extension@4.8.45) (2020-09-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.43...@patternfly/react-catalog-view-extension@4.8.44) (2020-09-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.42...@patternfly/react-catalog-view-extension@4.8.43) (2020-09-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.41...@patternfly/react-catalog-view-extension@4.8.42) (2020-09-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.40...@patternfly/react-catalog-view-extension@4.8.41) (2020-09-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.39...@patternfly/react-catalog-view-extension@4.8.40) (2020-09-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.38...@patternfly/react-catalog-view-extension@4.8.39) (2020-09-24) - - -### Bug Fixes - -* **demo-app:** replace CRA with webpack and ts-loader ([#4877](https://github.com/patternfly/patternfly-react/issues/4877)) ([1b64309](https://github.com/patternfly/patternfly-react/commit/1b6430943e14acf84fa54115b1a009930cf2372e)) - - - - - -## [4.8.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.37...@patternfly/react-catalog-view-extension@4.8.38) (2020-09-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.36...@patternfly/react-catalog-view-extension@4.8.37) (2020-09-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.35...@patternfly/react-catalog-view-extension@4.8.36) (2020-09-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.34...@patternfly/react-catalog-view-extension@4.8.35) (2020-09-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.33...@patternfly/react-catalog-view-extension@4.8.34) (2020-09-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.32...@patternfly/react-catalog-view-extension@4.8.33) (2020-09-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.31...@patternfly/react-catalog-view-extension@4.8.32) (2020-09-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.30...@patternfly/react-catalog-view-extension@4.8.31) (2020-09-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.29...@patternfly/react-catalog-view-extension@4.8.30) (2020-09-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.28...@patternfly/react-catalog-view-extension@4.8.29) (2020-09-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.27...@patternfly/react-catalog-view-extension@4.8.28) (2020-09-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.26...@patternfly/react-catalog-view-extension@4.8.27) (2020-09-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.25...@patternfly/react-catalog-view-extension@4.8.26) (2020-09-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.24...@patternfly/react-catalog-view-extension@4.8.25) (2020-09-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.23...@patternfly/react-catalog-view-extension@4.8.24) (2020-09-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.22...@patternfly/react-catalog-view-extension@4.8.23) (2020-09-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.21...@patternfly/react-catalog-view-extension@4.8.22) (2020-09-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.20...@patternfly/react-catalog-view-extension@4.8.21) (2020-09-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.19...@patternfly/react-catalog-view-extension@4.8.20) (2020-09-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.18...@patternfly/react-catalog-view-extension@4.8.19) (2020-08-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.17...@patternfly/react-catalog-view-extension@4.8.18) (2020-08-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.16...@patternfly/react-catalog-view-extension@4.8.17) (2020-08-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.15...@patternfly/react-catalog-view-extension@4.8.16) (2020-08-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.14...@patternfly/react-catalog-view-extension@4.8.15) (2020-08-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.13...@patternfly/react-catalog-view-extension@4.8.14) (2020-08-24) - - -### Bug Fixes - -* **docs:** use ids and h3s ([#4720](https://github.com/patternfly/patternfly-react/issues/4720)) ([a3f684f](https://github.com/patternfly/patternfly-react/commit/a3f684fa23cfce3d8e79b86206773292790cec5c)) - - - - - -## [4.8.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.12...@patternfly/react-catalog-view-extension@4.8.13) (2020-08-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.11...@patternfly/react-catalog-view-extension@4.8.12) (2020-08-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.10...@patternfly/react-catalog-view-extension@4.8.11) (2020-08-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.9...@patternfly/react-catalog-view-extension@4.8.10) (2020-08-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.8...@patternfly/react-catalog-view-extension@4.8.9) (2020-08-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.7...@patternfly/react-catalog-view-extension@4.8.8) (2020-08-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.6...@patternfly/react-catalog-view-extension@4.8.7) (2020-08-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.5...@patternfly/react-catalog-view-extension@4.8.6) (2020-08-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.4...@patternfly/react-catalog-view-extension@4.8.5) (2020-08-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.3...@patternfly/react-catalog-view-extension@4.8.4) (2020-08-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.2...@patternfly/react-catalog-view-extension@4.8.3) (2020-08-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.1...@patternfly/react-catalog-view-extension@4.8.2) (2020-08-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.8.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.8.0...@patternfly/react-catalog-view-extension@4.8.1) (2020-08-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.8.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.7.3...@patternfly/react-catalog-view-extension@4.8.0) (2020-08-04) - - -### Features - -* **NotificationDrawer:** Add notification drawer demo ([#4640](https://github.com/patternfly/patternfly-react/issues/4640)) ([3b9231d](https://github.com/patternfly/patternfly-react/commit/3b9231dab2fd92eb40e38d3a38ffb83562e1dbc2)) - - - - - -## [4.7.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.7.2...@patternfly/react-catalog-view-extension@4.7.3) (2020-08-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.7.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.7.1...@patternfly/react-catalog-view-extension@4.7.2) (2020-08-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.7.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.7.0...@patternfly/react-catalog-view-extension@4.7.1) (2020-08-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.7.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.6.4...@patternfly/react-catalog-view-extension@4.7.0) (2020-08-03) - - -### Features - -* **NotificationBadge:** add needs attention state and count ([#4516](https://github.com/patternfly/patternfly-react/issues/4516)) ([63c7cbf](https://github.com/patternfly/patternfly-react/commit/63c7cbf0beed5497ca7addf7fc6663229f37ab81)) - - - - - -## [4.6.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.6.3...@patternfly/react-catalog-view-extension@4.6.4) (2020-07-31) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.6.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.6.2...@patternfly/react-catalog-view-extension@4.6.3) (2020-07-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.6.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.6.1...@patternfly/react-catalog-view-extension@4.6.2) (2020-07-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.6.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.6.0...@patternfly/react-catalog-view-extension@4.6.1) (2020-07-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.6.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.18...@patternfly/react-catalog-view-extension@4.6.0) (2020-07-29) - - -### Features - -* **wiz:** make wiz nav items more easily discoverable ([#4425](https://github.com/patternfly/patternfly-react/issues/4425)) ([92384d4](https://github.com/patternfly/patternfly-react/commit/92384d40cb4d5e3171c6922d00e391ed290239ac)) - - - - - -## [4.5.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.17...@patternfly/react-catalog-view-extension@4.5.18) (2020-07-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.16...@patternfly/react-catalog-view-extension@4.5.17) (2020-07-29) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.15...@patternfly/react-catalog-view-extension@4.5.16) (2020-07-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.14...@patternfly/react-catalog-view-extension@4.5.15) (2020-07-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.13...@patternfly/react-catalog-view-extension@4.5.14) (2020-07-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.12...@patternfly/react-catalog-view-extension@4.5.13) (2020-07-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.11...@patternfly/react-catalog-view-extension@4.5.12) (2020-07-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.10...@patternfly/react-catalog-view-extension@4.5.11) (2020-07-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.9...@patternfly/react-catalog-view-extension@4.5.10) (2020-07-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.8...@patternfly/react-catalog-view-extension@4.5.9) (2020-07-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.7...@patternfly/react-catalog-view-extension@4.5.8) (2020-07-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.6...@patternfly/react-catalog-view-extension@4.5.7) (2020-07-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.5...@patternfly/react-catalog-view-extension@4.5.6) (2020-07-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.4...@patternfly/react-catalog-view-extension@4.5.5) (2020-07-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.3...@patternfly/react-catalog-view-extension@4.5.4) (2020-07-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.2...@patternfly/react-catalog-view-extension@4.5.3) (2020-07-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.1...@patternfly/react-catalog-view-extension@4.5.2) (2020-07-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.5.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.5.0...@patternfly/react-catalog-view-extension@4.5.1) (2020-07-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.5.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.27...@patternfly/react-catalog-view-extension@4.5.0) (2020-07-16) - - -### Features - -* **FormGroup, FormSelect, TextInput, TextArea:** Add warning state ([#4554](https://github.com/patternfly/patternfly-react/issues/4554)) ([4e7f69a](https://github.com/patternfly/patternfly-react/commit/4e7f69a35abd247db99bd946a2c9bc931c335564)) - - - - - -## [4.4.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.26...@patternfly/react-catalog-view-extension@4.4.27) (2020-07-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.25...@patternfly/react-catalog-view-extension@4.4.26) (2020-07-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.24...@patternfly/react-catalog-view-extension@4.4.25) (2020-07-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.23...@patternfly/react-catalog-view-extension@4.4.24) (2020-07-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.22...@patternfly/react-catalog-view-extension@4.4.23) (2020-07-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.21...@patternfly/react-catalog-view-extension@4.4.22) (2020-07-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.20...@patternfly/react-catalog-view-extension@4.4.21) (2020-07-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.19...@patternfly/react-catalog-view-extension@4.4.20) (2020-07-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.18...@patternfly/react-catalog-view-extension@4.4.19) (2020-07-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.17...@patternfly/react-catalog-view-extension@4.4.18) (2020-07-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.16...@patternfly/react-catalog-view-extension@4.4.17) (2020-07-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.15...@patternfly/react-catalog-view-extension@4.4.16) (2020-07-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.14...@patternfly/react-catalog-view-extension@4.4.15) (2020-07-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.13...@patternfly/react-catalog-view-extension@4.4.14) (2020-07-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.12...@patternfly/react-catalog-view-extension@4.4.13) (2020-07-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.11...@patternfly/react-catalog-view-extension@4.4.12) (2020-07-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.10...@patternfly/react-catalog-view-extension@4.4.11) (2020-07-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.9...@patternfly/react-catalog-view-extension@4.4.10) (2020-07-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.8...@patternfly/react-catalog-view-extension@4.4.9) (2020-06-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.7...@patternfly/react-catalog-view-extension@4.4.8) (2020-06-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.6...@patternfly/react-catalog-view-extension@4.4.7) (2020-06-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.5...@patternfly/react-catalog-view-extension@4.4.6) (2020-06-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.4...@patternfly/react-catalog-view-extension@4.4.5) (2020-06-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.3...@patternfly/react-catalog-view-extension@4.4.4) (2020-06-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.2...@patternfly/react-catalog-view-extension@4.4.3) (2020-06-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.1...@patternfly/react-catalog-view-extension@4.4.2) (2020-06-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.4.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.4.0...@patternfly/react-catalog-view-extension@4.4.1) (2020-06-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.27...@patternfly/react-catalog-view-extension@4.4.0) (2020-06-19) - - -### Features - -* **Divider:** Add support for insets to the Divider ([#4410](https://github.com/patternfly/patternfly-react/issues/4410)) ([32916b8](https://github.com/patternfly/patternfly-react/commit/32916b89fcf631eb498ae0b64faffec756242127)) - - - - - -## [4.3.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.26...@patternfly/react-catalog-view-extension@4.3.27) (2020-06-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.25...@patternfly/react-catalog-view-extension@4.3.26) (2020-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.24...@patternfly/react-catalog-view-extension@4.3.25) (2020-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.23...@patternfly/react-catalog-view-extension@4.3.24) (2020-06-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.22...@patternfly/react-catalog-view-extension@4.3.23) (2020-06-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.21...@patternfly/react-catalog-view-extension@4.3.22) (2020-06-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.20...@patternfly/react-catalog-view-extension@4.3.21) (2020-06-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.19...@patternfly/react-catalog-view-extension@4.3.20) (2020-06-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.18...@patternfly/react-catalog-view-extension@4.3.19) (2020-06-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.17...@patternfly/react-catalog-view-extension@4.3.18) (2020-06-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.16...@patternfly/react-catalog-view-extension@4.3.17) (2020-06-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.15...@patternfly/react-catalog-view-extension@4.3.16) (2020-06-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.14...@patternfly/react-catalog-view-extension@4.3.15) (2020-06-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.13...@patternfly/react-catalog-view-extension@4.3.14) (2020-06-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.12...@patternfly/react-catalog-view-extension@4.3.13) (2020-06-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.11...@patternfly/react-catalog-view-extension@4.3.12) (2020-06-05) - - -### Bug Fixes - -* **docs:** add upgrade guide ([#4298](https://github.com/patternfly/patternfly-react/issues/4298)) ([4ee8805](https://github.com/patternfly/patternfly-react/commit/4ee8805ab9b232ebbe280313d4ae3e53bd78fb70)) - - - - - -## [4.3.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.10...@patternfly/react-catalog-view-extension@4.3.11) (2020-06-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.9...@patternfly/react-catalog-view-extension@4.3.10) (2020-06-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.8...@patternfly/react-catalog-view-extension@4.3.9) (2020-06-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.7...@patternfly/react-catalog-view-extension@4.3.8) (2020-06-01) - - -### Bug Fixes - -* **breakpoints:** make API consistent and appear in docs ([#4310](https://github.com/patternfly/patternfly-react/issues/4310)) ([ac1afa6](https://github.com/patternfly/patternfly-react/commit/ac1afa60067346c658fcb160534d9ddaf7dafbc6)) - - - - - -## [4.3.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.6...@patternfly/react-catalog-view-extension@4.3.7) (2020-05-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.5...@patternfly/react-catalog-view-extension@4.3.6) (2020-05-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.4...@patternfly/react-catalog-view-extension@4.3.5) (2020-05-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.3...@patternfly/react-catalog-view-extension@4.3.4) (2020-05-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.2...@patternfly/react-catalog-view-extension@4.3.3) (2020-05-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.1...@patternfly/react-catalog-view-extension@4.3.2) (2020-05-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [4.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@4.3.0...@patternfly/react-catalog-view-extension@4.3.1) (2020-05-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [4.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.66...@patternfly/react-catalog-view-extension@4.3.0) (2020-05-15) - - -### Features - -* **master:** merge v4 ([#4255](https://github.com/patternfly/patternfly-react/issues/4255)) ([567c0b8](https://github.com/patternfly/patternfly-react/commit/567c0b88b10d2cd629ce380745a24dacdf9dd3d1)), closes [#3868](https://github.com/patternfly/patternfly-react/issues/3868) [#3915](https://github.com/patternfly/patternfly-react/issues/3915) [#3921](https://github.com/patternfly/patternfly-react/issues/3921) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3843](https://github.com/patternfly/patternfly-react/issues/3843) [#3884](https://github.com/patternfly/patternfly-react/issues/3884) [#3609](https://github.com/patternfly/patternfly-react/issues/3609) [#3880](https://github.com/patternfly/patternfly-react/issues/3880) [#3865](https://github.com/patternfly/patternfly-react/issues/3865) [#3894](https://github.com/patternfly/patternfly-react/issues/3894) [#3897](https://github.com/patternfly/patternfly-react/issues/3897) [#3892](https://github.com/patternfly/patternfly-react/issues/3892) [#3891](https://github.com/patternfly/patternfly-react/issues/3891) [#3908](https://github.com/patternfly/patternfly-react/issues/3908) [#3910](https://github.com/patternfly/patternfly-react/issues/3910) [#3861](https://github.com/patternfly/patternfly-react/issues/3861) [#3877](https://github.com/patternfly/patternfly-react/issues/3877) [#3916](https://github.com/patternfly/patternfly-react/issues/3916) [#3886](https://github.com/patternfly/patternfly-react/issues/3886) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3927](https://github.com/patternfly/patternfly-react/issues/3927) [#3933](https://github.com/patternfly/patternfly-react/issues/3933) [#3221](https://github.com/patternfly/patternfly-react/issues/3221) [#3873](https://github.com/patternfly/patternfly-react/issues/3873) [#3928](https://github.com/patternfly/patternfly-react/issues/3928) [#3929](https://github.com/patternfly/patternfly-react/issues/3929) [#2582](https://github.com/patternfly/patternfly-react/issues/2582) [#3296](https://github.com/patternfly/patternfly-react/issues/3296) [#3924](https://github.com/patternfly/patternfly-react/issues/3924) [#1529](https://github.com/patternfly/patternfly-react/issues/1529) [#3903](https://github.com/patternfly/patternfly-react/issues/3903) [#3904](https://github.com/patternfly/patternfly-react/issues/3904) [#3974](https://github.com/patternfly/patternfly-react/issues/3974) [#3970](https://github.com/patternfly/patternfly-react/issues/3970) [#3920](https://github.com/patternfly/patternfly-react/issues/3920) [#3945](https://github.com/patternfly/patternfly-react/issues/3945) [#3978](https://github.com/patternfly/patternfly-react/issues/3978) [#3962](https://github.com/patternfly/patternfly-react/issues/3962) [#3975](https://github.com/patternfly/patternfly-react/issues/3975) [#3906](https://github.com/patternfly/patternfly-react/issues/3906) [#3870](https://github.com/patternfly/patternfly-react/issues/3870) [#3958](https://github.com/patternfly/patternfly-react/issues/3958) [#3922](https://github.com/patternfly/patternfly-react/issues/3922) [#3985](https://github.com/patternfly/patternfly-react/issues/3985) [#3991](https://github.com/patternfly/patternfly-react/issues/3991) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3843](https://github.com/patternfly/patternfly-react/issues/3843) [#3884](https://github.com/patternfly/patternfly-react/issues/3884) [#3609](https://github.com/patternfly/patternfly-react/issues/3609) [#3880](https://github.com/patternfly/patternfly-react/issues/3880) [#3865](https://github.com/patternfly/patternfly-react/issues/3865) [#3894](https://github.com/patternfly/patternfly-react/issues/3894) [#3897](https://github.com/patternfly/patternfly-react/issues/3897) [#3892](https://github.com/patternfly/patternfly-react/issues/3892) [#3891](https://github.com/patternfly/patternfly-react/issues/3891) [#3908](https://github.com/patternfly/patternfly-react/issues/3908) [#3910](https://github.com/patternfly/patternfly-react/issues/3910) [#3861](https://github.com/patternfly/patternfly-react/issues/3861) [#3877](https://github.com/patternfly/patternfly-react/issues/3877) [#3916](https://github.com/patternfly/patternfly-react/issues/3916) [#3844](https://github.com/patternfly/patternfly-react/issues/3844) [#3919](https://github.com/patternfly/patternfly-react/issues/3919) [#3923](https://github.com/patternfly/patternfly-react/issues/3923) [#3838](https://github.com/patternfly/patternfly-react/issues/3838) [#3895](https://github.com/patternfly/patternfly-react/issues/3895) [#3896](https://github.com/patternfly/patternfly-react/issues/3896) [#3771](https://github.com/patternfly/patternfly-react/issues/3771) [#3940](https://github.com/patternfly/patternfly-react/issues/3940) [#3941](https://github.com/patternfly/patternfly-react/issues/3941) [#3441](https://github.com/patternfly/patternfly-react/issues/3441) [#3950](https://github.com/patternfly/patternfly-react/issues/3950) [#3642](https://github.com/patternfly/patternfly-react/issues/3642) [#3964](https://github.com/patternfly/patternfly-react/issues/3964) [#3968](https://github.com/patternfly/patternfly-react/issues/3968) [#3967](https://github.com/patternfly/patternfly-react/issues/3967) [#3971](https://github.com/patternfly/patternfly-react/issues/3971) [#3942](https://github.com/patternfly/patternfly-react/issues/3942) [#3898](https://github.com/patternfly/patternfly-react/issues/3898) [#3898](https://github.com/patternfly/patternfly-react/issues/3898) [#3976](https://github.com/patternfly/patternfly-react/issues/3976) [#3889](https://github.com/patternfly/patternfly-react/issues/3889) [#3641](https://github.com/patternfly/patternfly-react/issues/3641) [#3982](https://github.com/patternfly/patternfly-react/issues/3982) [#3979](https://github.com/patternfly/patternfly-react/issues/3979) [#3989](https://github.com/patternfly/patternfly-react/issues/3989) [#4017](https://github.com/patternfly/patternfly-react/issues/4017) [#4022](https://github.com/patternfly/patternfly-react/issues/4022) [#4014](https://github.com/patternfly/patternfly-react/issues/4014) [#4048](https://github.com/patternfly/patternfly-react/issues/4048) [#4050](https://github.com/patternfly/patternfly-react/issues/4050) [#4051](https://github.com/patternfly/patternfly-react/issues/4051) [#4058](https://github.com/patternfly/patternfly-react/issues/4058) [#4030](https://github.com/patternfly/patternfly-react/issues/4030) [#4031](https://github.com/patternfly/patternfly-react/issues/4031) [#3996](https://github.com/patternfly/patternfly-react/issues/3996) [#4001](https://github.com/patternfly/patternfly-react/issues/4001) [#4004](https://github.com/patternfly/patternfly-react/issues/4004) [#4066](https://github.com/patternfly/patternfly-react/issues/4066) [#4021](https://github.com/patternfly/patternfly-react/issues/4021) [#4061](https://github.com/patternfly/patternfly-react/issues/4061) [#4026](https://github.com/patternfly/patternfly-react/issues/4026) [#4069](https://github.com/patternfly/patternfly-react/issues/4069) [#4073](https://github.com/patternfly/patternfly-react/issues/4073) [#4036](https://github.com/patternfly/patternfly-react/issues/4036) [#4019](https://github.com/patternfly/patternfly-react/issues/4019) [#4081](https://github.com/patternfly/patternfly-react/issues/4081) [#4033](https://github.com/patternfly/patternfly-react/issues/4033) [#4065](https://github.com/patternfly/patternfly-react/issues/4065) [#4078](https://github.com/patternfly/patternfly-react/issues/4078) [#4032](https://github.com/patternfly/patternfly-react/issues/4032) [#4029](https://github.com/patternfly/patternfly-react/issues/4029) [#4064](https://github.com/patternfly/patternfly-react/issues/4064) [#4063](https://github.com/patternfly/patternfly-react/issues/4063) [#2593](https://github.com/patternfly/patternfly-react/issues/2593) [#4076](https://github.com/patternfly/patternfly-react/issues/4076) [#4099](https://github.com/patternfly/patternfly-react/issues/4099) [#4038](https://github.com/patternfly/patternfly-react/issues/4038) [#4116](https://github.com/patternfly/patternfly-react/issues/4116) [#3960](https://github.com/patternfly/patternfly-react/issues/3960) [#4121](https://github.com/patternfly/patternfly-react/issues/4121) [#4123](https://github.com/patternfly/patternfly-react/issues/4123) [#4025](https://github.com/patternfly/patternfly-react/issues/4025) [#4126](https://github.com/patternfly/patternfly-react/issues/4126) [#4122](https://github.com/patternfly/patternfly-react/issues/4122) [#4086](https://github.com/patternfly/patternfly-react/issues/4086) [#4127](https://github.com/patternfly/patternfly-react/issues/4127) [#4129](https://github.com/patternfly/patternfly-react/issues/4129) [#4111](https://github.com/patternfly/patternfly-react/issues/4111) [#4136](https://github.com/patternfly/patternfly-react/issues/4136) [#4138](https://github.com/patternfly/patternfly-react/issues/4138) [#4141](https://github.com/patternfly/patternfly-react/issues/4141) [#4145](https://github.com/patternfly/patternfly-react/issues/4145) [#4034](https://github.com/patternfly/patternfly-react/issues/4034) [#4144](https://github.com/patternfly/patternfly-react/issues/4144) [#4152](https://github.com/patternfly/patternfly-react/issues/4152) [#4158](https://github.com/patternfly/patternfly-react/issues/4158) [#4157](https://github.com/patternfly/patternfly-react/issues/4157) [#4156](https://github.com/patternfly/patternfly-react/issues/4156) [#4147](https://github.com/patternfly/patternfly-react/issues/4147) [#4159](https://github.com/patternfly/patternfly-react/issues/4159) [#4170](https://github.com/patternfly/patternfly-react/issues/4170) [#4142](https://github.com/patternfly/patternfly-react/issues/4142) [#4175](https://github.com/patternfly/patternfly-react/issues/4175) [#4176](https://github.com/patternfly/patternfly-react/issues/4176) [#4187](https://github.com/patternfly/patternfly-react/issues/4187) [#4188](https://github.com/patternfly/patternfly-react/issues/4188) [#4140](https://github.com/patternfly/patternfly-react/issues/4140) [#4193](https://github.com/patternfly/patternfly-react/issues/4193) [#4154](https://github.com/patternfly/patternfly-react/issues/4154) [#4192](https://github.com/patternfly/patternfly-react/issues/4192) [#4190](https://github.com/patternfly/patternfly-react/issues/4190) [#4199](https://github.com/patternfly/patternfly-react/issues/4199) [#4133](https://github.com/patternfly/patternfly-react/issues/4133) [#4165](https://github.com/patternfly/patternfly-react/issues/4165) [#4208](https://github.com/patternfly/patternfly-react/issues/4208) [#4212](https://github.com/patternfly/patternfly-react/issues/4212) [#4130](https://github.com/patternfly/patternfly-react/issues/4130) [#4219](https://github.com/patternfly/patternfly-react/issues/4219) [#4166](https://github.com/patternfly/patternfly-react/issues/4166) [#4202](https://github.com/patternfly/patternfly-react/issues/4202) [#4216](https://github.com/patternfly/patternfly-react/issues/4216) [#4225](https://github.com/patternfly/patternfly-react/issues/4225) [#4221](https://github.com/patternfly/patternfly-react/issues/4221) [#4146](https://github.com/patternfly/patternfly-react/issues/4146) [#3951](https://github.com/patternfly/patternfly-react/issues/3951) [#3681](https://github.com/patternfly/patternfly-react/issues/3681) [#4243](https://github.com/patternfly/patternfly-react/issues/4243) [#4220](https://github.com/patternfly/patternfly-react/issues/4220) [#4153](https://github.com/patternfly/patternfly-react/issues/4153) [#4209](https://github.com/patternfly/patternfly-react/issues/4209) [#4249](https://github.com/patternfly/patternfly-react/issues/4249) [#4239](https://github.com/patternfly/patternfly-react/issues/4239) [#4247](https://github.com/patternfly/patternfly-react/issues/4247) [#4246](https://github.com/patternfly/patternfly-react/issues/4246) [#3684](https://github.com/patternfly/patternfly-react/issues/3684) [#4223](https://github.com/patternfly/patternfly-react/issues/4223) [#4195](https://github.com/patternfly/patternfly-react/issues/4195) [#4254](https://github.com/patternfly/patternfly-react/issues/4254) -* **packages:** bump core to 4.10.21 ([#4257](https://github.com/patternfly/patternfly-react/issues/4257)) ([2e2676c](https://github.com/patternfly/patternfly-react/commit/2e2676ce6bc34f5e20231ca066d26ea4c3ac95e4)) - - - - - -## [1.4.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.65...@patternfly/react-catalog-view-extension@1.4.66) (2020-05-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.64...@patternfly/react-catalog-view-extension@1.4.65) (2020-05-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.63...@patternfly/react-catalog-view-extension@1.4.64) (2020-05-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.62...@patternfly/react-catalog-view-extension@1.4.63) (2020-05-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.61...@patternfly/react-catalog-view-extension@1.4.62) (2020-05-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.60...@patternfly/react-catalog-view-extension@1.4.61) (2020-05-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.59...@patternfly/react-catalog-view-extension@1.4.60) (2020-04-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.58...@patternfly/react-catalog-view-extension@1.4.59) (2020-04-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.57...@patternfly/react-catalog-view-extension@1.4.58) (2020-04-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.56...@patternfly/react-catalog-view-extension@1.4.57) (2020-04-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.55...@patternfly/react-catalog-view-extension@1.4.56) (2020-04-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.54...@patternfly/react-catalog-view-extension@1.4.55) (2020-04-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.53...@patternfly/react-catalog-view-extension@1.4.54) (2020-04-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.52...@patternfly/react-catalog-view-extension@1.4.53) (2020-04-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.51...@patternfly/react-catalog-view-extension@1.4.52) (2020-04-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.50...@patternfly/react-catalog-view-extension@1.4.51) (2020-04-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.49...@patternfly/react-catalog-view-extension@1.4.50) (2020-04-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.48...@patternfly/react-catalog-view-extension@1.4.49) (2020-04-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.47...@patternfly/react-catalog-view-extension@1.4.48) (2020-04-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.46...@patternfly/react-catalog-view-extension@1.4.47) (2020-03-31) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.45...@patternfly/react-catalog-view-extension@1.4.46) (2020-03-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.44...@patternfly/react-catalog-view-extension@1.4.45) (2020-03-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.43...@patternfly/react-catalog-view-extension@1.4.44) (2020-03-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.42...@patternfly/react-catalog-view-extension@1.4.43) (2020-03-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.41...@patternfly/react-catalog-view-extension@1.4.42) (2020-03-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.40...@patternfly/react-catalog-view-extension@1.4.41) (2020-03-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.39...@patternfly/react-catalog-view-extension@1.4.40) (2020-03-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.38...@patternfly/react-catalog-view-extension@1.4.39) (2020-03-24) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.37...@patternfly/react-catalog-view-extension@1.4.38) (2020-03-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.36...@patternfly/react-catalog-view-extension@1.4.37) (2020-03-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.35...@patternfly/react-catalog-view-extension@1.4.36) (2020-03-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.34...@patternfly/react-catalog-view-extension@1.4.35) (2020-03-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.33...@patternfly/react-catalog-view-extension@1.4.34) (2020-03-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.32...@patternfly/react-catalog-view-extension@1.4.33) (2020-03-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.31...@patternfly/react-catalog-view-extension@1.4.32) (2020-03-17) - - -### Bug Fixes - -* **core,table:** forward ref types ([#3919](https://github.com/patternfly/patternfly-react/issues/3919)) ([2210ec2](https://github.com/patternfly/patternfly-react/commit/2210ec2c142a385f85de8b0bac9c61a61521186d)) - - - - - -## [1.4.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.29...@patternfly/react-catalog-view-extension@1.4.31) (2020-03-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.29...@patternfly/react-catalog-view-extension@1.4.30) (2020-03-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.28...@patternfly/react-catalog-view-extension@1.4.29) (2020-03-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.27...@patternfly/react-catalog-view-extension@1.4.28) (2020-03-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.26...@patternfly/react-catalog-view-extension@1.4.27) (2020-03-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.25...@patternfly/react-catalog-view-extension@1.4.26) (2020-03-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.24...@patternfly/react-catalog-view-extension@1.4.25) (2020-03-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.23...@patternfly/react-catalog-view-extension@1.4.24) (2020-03-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.22...@patternfly/react-catalog-view-extension@1.4.23) (2020-03-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.21...@patternfly/react-catalog-view-extension@1.4.22) (2020-03-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.20...@patternfly/react-catalog-view-extension@1.4.21) (2020-03-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.19...@patternfly/react-catalog-view-extension@1.4.20) (2020-03-02) - - -### Bug Fixes - -* **CatalogTile:** Removed truncation and maxLength props ([#3830](https://github.com/patternfly/patternfly-react/issues/3830)) ([e0402d0](https://github.com/patternfly/patternfly-react/commit/e0402d02a2af703e7520f521da91ca39ef1a8a64)), closes [#3471](https://github.com/patternfly/patternfly-react/issues/3471) - - - - - -## [1.4.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.18...@patternfly/react-catalog-view-extension@1.4.19) (2020-03-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.17...@patternfly/react-catalog-view-extension@1.4.18) (2020-02-28) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.16...@patternfly/react-catalog-view-extension@1.4.17) (2020-02-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.15...@patternfly/react-catalog-view-extension@1.4.16) (2020-02-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.14...@patternfly/react-catalog-view-extension@1.4.15) (2020-02-26) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.13...@patternfly/react-catalog-view-extension@1.4.14) (2020-02-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.12...@patternfly/react-catalog-view-extension@1.4.13) (2020-02-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.11...@patternfly/react-catalog-view-extension@1.4.12) (2020-02-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.10...@patternfly/react-catalog-view-extension@1.4.11) (2020-02-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.9...@patternfly/react-catalog-view-extension@1.4.10) (2020-02-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.8...@patternfly/react-catalog-view-extension@1.4.9) (2020-02-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.7...@patternfly/react-catalog-view-extension@1.4.8) (2020-02-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.6...@patternfly/react-catalog-view-extension@1.4.7) (2020-02-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.5...@patternfly/react-catalog-view-extension@1.4.6) (2020-02-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.4...@patternfly/react-catalog-view-extension@1.4.5) (2020-02-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.3...@patternfly/react-catalog-view-extension@1.4.4) (2020-02-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.2...@patternfly/react-catalog-view-extension@1.4.3) (2020-02-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.1...@patternfly/react-catalog-view-extension@1.4.2) (2020-02-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.4.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.4.0...@patternfly/react-catalog-view-extension@1.4.1) (2020-02-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [1.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.22...@patternfly/react-catalog-view-extension@1.4.0) (2020-02-14) - - -### Features - -* **inline-edit:** add row level inline editing feature to Table ([#3581](https://github.com/patternfly/patternfly-react/issues/3581)) ([498d49f](https://github.com/patternfly/patternfly-react/commit/498d49fcc5cc9188197ddc7cd6468907fdd8224d)) - - - - - -## [1.3.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.21...@patternfly/react-catalog-view-extension@1.3.22) (2020-02-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.20...@patternfly/react-catalog-view-extension@1.3.21) (2020-02-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.19...@patternfly/react-catalog-view-extension@1.3.20) (2020-02-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.18...@patternfly/react-catalog-view-extension@1.3.19) (2020-02-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.17...@patternfly/react-catalog-view-extension@1.3.18) (2020-02-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.16...@patternfly/react-catalog-view-extension@1.3.17) (2020-02-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.15...@patternfly/react-catalog-view-extension@1.3.16) (2020-02-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.14...@patternfly/react-catalog-view-extension@1.3.15) (2020-02-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.13...@patternfly/react-catalog-view-extension@1.3.14) (2020-02-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.12...@patternfly/react-catalog-view-extension@1.3.13) (2020-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.11...@patternfly/react-catalog-view-extension@1.3.12) (2020-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.10...@patternfly/react-catalog-view-extension@1.3.11) (2020-02-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.9...@patternfly/react-catalog-view-extension@1.3.10) (2020-02-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.8...@patternfly/react-catalog-view-extension@1.3.9) (2020-02-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.7...@patternfly/react-catalog-view-extension@1.3.8) (2020-02-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.6...@patternfly/react-catalog-view-extension@1.3.7) (2020-02-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.5...@patternfly/react-catalog-view-extension@1.3.6) (2020-02-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.4...@patternfly/react-catalog-view-extension@1.3.5) (2020-02-03) - - -### Bug Fixes - -* **Catalog tile:** Reduce padding between badge and logo ([#3644](https://github.com/patternfly/patternfly-react/issues/3644)) ([763e55a](https://github.com/patternfly/patternfly-react/commit/763e55add52a8d07fb5a566626030770f7a7cd06)) - - - - - -## [1.3.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.3...@patternfly/react-catalog-view-extension@1.3.4) (2020-02-03) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.2...@patternfly/react-catalog-view-extension@1.3.3) (2020-02-03) - - -### Bug Fixes - -* **Catalog view extension:** Many styles on examples stopped working. This change restores all styles. ([#3635](https://github.com/patternfly/patternfly-react/issues/3635)) ([e1d176a](https://github.com/patternfly/patternfly-react/commit/e1d176aee9b683b0a9ddf163aa31fa44c9e7e4bd)), closes [#3633](https://github.com/patternfly/patternfly-react/issues/3633) - - - - - -## [1.3.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.1...@patternfly/react-catalog-view-extension@1.3.2) (2020-01-31) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.3.0...@patternfly/react-catalog-view-extension@1.3.1) (2020-01-31) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [1.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.7...@patternfly/react-catalog-view-extension@1.3.0) (2020-01-31) - - -### Features - -* **icons:** use absolute import paths ([#3517](https://github.com/patternfly/patternfly-react/issues/3517)) ([897d359](https://github.com/patternfly/patternfly-react/commit/897d359a48ac2ce6ddea68bbdcfe0ae2f05544bd)) - - - - - -## [1.2.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.6...@patternfly/react-catalog-view-extension@1.2.7) (2020-01-30) - - -### Bug Fixes - -* **a11y:** fix a11y errors and enable a11y in CI ([#3593](https://github.com/patternfly/patternfly-react/issues/3593)) ([d20cab7](https://github.com/patternfly/patternfly-react/commit/d20cab7c9f39f7d1cd195f0a3b50aff3b7c3a0d3)) -* **Catalog Tile:** Adjusted max height of header image ([#3628](https://github.com/patternfly/patternfly-react/issues/3628)) ([0320821](https://github.com/patternfly/patternfly-react/commit/03208217da6f134cfcb49dc244b46b76108c2b3c)) - - - - - -## [1.2.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.5...@patternfly/react-catalog-view-extension@1.2.6) (2020-01-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.2.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.4...@patternfly/react-catalog-view-extension@1.2.5) (2020-01-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.2.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.3...@patternfly/react-catalog-view-extension@1.2.4) (2020-01-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.2.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.2...@patternfly/react-catalog-view-extension@1.2.3) (2020-01-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.2.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.1...@patternfly/react-catalog-view-extension@1.2.2) (2020-01-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.2.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.2.0...@patternfly/react-catalog-view-extension@1.2.1) (2020-01-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# [1.2.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.86...@patternfly/react-catalog-view-extension@1.2.0) (2020-01-24) - - -### Features - -* **pf4:** Use absolute import paths for react core in pf4 packages. ([#3525](https://github.com/patternfly/patternfly-react/issues/3525)) ([65d0b3d](https://github.com/patternfly/patternfly-react/commit/65d0b3d1e04610895f122c1313d1442360356f13)), closes [#3155](https://github.com/patternfly/patternfly-react/issues/3155) - - - - - -## [1.1.86](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.85...@patternfly/react-catalog-view-extension@1.1.86) (2020-01-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.85](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.84...@patternfly/react-catalog-view-extension@1.1.85) (2020-01-23) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.84](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.83...@patternfly/react-catalog-view-extension@1.1.84) (2020-01-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.83](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.82...@patternfly/react-catalog-view-extension@1.1.83) (2020-01-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.82](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.81...@patternfly/react-catalog-view-extension@1.1.82) (2020-01-22) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.81](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.80...@patternfly/react-catalog-view-extension@1.1.81) (2020-01-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.80](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.79...@patternfly/react-catalog-view-extension@1.1.80) (2020-01-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.78...@patternfly/react-catalog-view-extension@1.1.79) (2020-01-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.77...@patternfly/react-catalog-view-extension@1.1.78) (2020-01-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.76...@patternfly/react-catalog-view-extension@1.1.77) (2020-01-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.75...@patternfly/react-catalog-view-extension@1.1.76) (2020-01-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.74...@patternfly/react-catalog-view-extension@1.1.75) (2020-01-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.73...@patternfly/react-catalog-view-extension@1.1.74) (2020-01-15) - - -### Bug Fixes - -* **linting:** initial eslint fixes for react-core-style-system *.md f… ([#3505](https://github.com/patternfly/patternfly-react/issues/3505)) ([9a0f90b](https://github.com/patternfly/patternfly-react/commit/9a0f90b9eac926a88e23559d31ebcc9599875406)) - - - - - -## [1.1.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.72...@patternfly/react-catalog-view-extension@1.1.73) (2020-01-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.71...@patternfly/react-catalog-view-extension@1.1.72) (2020-01-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.70...@patternfly/react-catalog-view-extension@1.1.71) (2020-01-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.69...@patternfly/react-catalog-view-extension@1.1.70) (2020-01-13) - - -### Bug Fixes - -* **linting:** eslint for *.md file fixes ([#3493](https://github.com/patternfly/patternfly-react/issues/3493)) ([4574ad2](https://github.com/patternfly/patternfly-react/commit/4574ad2af8d9ee508124b986d4a63a67c8fd70d7)) - - - - - -## [1.1.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.68...@patternfly/react-catalog-view-extension@1.1.69) (2020-01-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.67...@patternfly/react-catalog-view-extension@1.1.68) (2020-01-10) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.66...@patternfly/react-catalog-view-extension@1.1.67) (2020-01-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.65...@patternfly/react-catalog-view-extension@1.1.66) (2020-01-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.64...@patternfly/react-catalog-view-extension@1.1.65) (2020-01-09) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.63...@patternfly/react-catalog-view-extension@1.1.64) (2020-01-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.62...@patternfly/react-catalog-view-extension@1.1.63) (2020-01-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.61...@patternfly/react-catalog-view-extension@1.1.62) (2020-01-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.60...@patternfly/react-catalog-view-extension@1.1.61) (2020-01-07) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.59...@patternfly/react-catalog-view-extension@1.1.60) (2019-12-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.58...@patternfly/react-catalog-view-extension@1.1.59) (2019-12-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.57...@patternfly/react-catalog-view-extension@1.1.58) (2019-12-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.56...@patternfly/react-catalog-view-extension@1.1.57) (2019-12-17) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.55...@patternfly/react-catalog-view-extension@1.1.56) (2019-12-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.54...@patternfly/react-catalog-view-extension@1.1.55) (2019-12-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.53...@patternfly/react-catalog-view-extension@1.1.54) (2019-12-16) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.52...@patternfly/react-catalog-view-extension@1.1.53) (2019-12-13) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.51...@patternfly/react-catalog-view-extension@1.1.52) (2019-12-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.50...@patternfly/react-catalog-view-extension@1.1.51) (2019-12-12) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.49...@patternfly/react-catalog-view-extension@1.1.50) (2019-12-11) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.48...@patternfly/react-catalog-view-extension@1.1.49) (2019-12-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.47...@patternfly/react-catalog-view-extension@1.1.48) (2019-12-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.46...@patternfly/react-catalog-view-extension@1.1.47) (2019-12-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.45...@patternfly/react-catalog-view-extension@1.1.46) (2019-12-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.44...@patternfly/react-catalog-view-extension@1.1.45) (2019-12-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.43...@patternfly/react-catalog-view-extension@1.1.44) (2019-12-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.42...@patternfly/react-catalog-view-extension@1.1.43) (2019-12-04) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.41...@patternfly/react-catalog-view-extension@1.1.42) (2019-12-03) - - -### Bug Fixes - -* **FilterSidePanel:** pass remaining props to checkbox component ([#3374](https://github.com/patternfly/patternfly-react/issues/3374)) ([0050615](https://github.com/patternfly/patternfly-react/commit/005061506dde5fdf903e93a813b612187d650f51)) - - - - - -## [1.1.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.40...@patternfly/react-catalog-view-extension@1.1.41) (2019-12-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.39...@patternfly/react-catalog-view-extension@1.1.40) (2019-12-02) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.38...@patternfly/react-catalog-view-extension@1.1.39) (2019-11-27) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.37...@patternfly/react-catalog-view-extension@1.1.38) (2019-11-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.36...@patternfly/react-catalog-view-extension@1.1.37) (2019-11-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.35...@patternfly/react-catalog-view-extension@1.1.36) (2019-11-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.34...@patternfly/react-catalog-view-extension@1.1.35) (2019-11-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.33...@patternfly/react-catalog-view-extension@1.1.34) (2019-11-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.32...@patternfly/react-catalog-view-extension@1.1.33) (2019-11-21) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.31...@patternfly/react-catalog-view-extension@1.1.32) (2019-11-20) - - -### Bug Fixes - -* **catalog-view-extension:** remove unused packages ([#3332](https://github.com/patternfly/patternfly-react/issues/3332)) ([a3fcfcc](https://github.com/patternfly/patternfly-react/commit/a3fcfcc35792fb9962fce75a6e1fa1155cef3e3c)) - - - - - -## [1.1.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.30...@patternfly/react-catalog-view-extension@1.1.31) (2019-11-20) - - -### Bug Fixes - -* **CatalogTile:** Removed unneeded selector ([#3331](https://github.com/patternfly/patternfly-react/issues/3331)) ([5892d50](https://github.com/patternfly/patternfly-react/commit/5892d5080270db398b5fa84772b9ea2cb3d0f599)) - - - - - -## [1.1.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.29...@patternfly/react-catalog-view-extension@1.1.30) (2019-11-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.28...@patternfly/react-catalog-view-extension@1.1.29) (2019-11-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.27...@patternfly/react-catalog-view-extension@1.1.28) (2019-11-20) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.26...@patternfly/react-catalog-view-extension@1.1.27) (2019-11-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.25...@patternfly/react-catalog-view-extension@1.1.26) (2019-11-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.24...@patternfly/react-catalog-view-extension@1.1.25) (2019-11-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.23...@patternfly/react-catalog-view-extension@1.1.24) (2019-11-19) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.22...@patternfly/react-catalog-view-extension@1.1.23) (2019-11-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.21...@patternfly/react-catalog-view-extension@1.1.22) (2019-11-18) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.20...@patternfly/react-catalog-view-extension@1.1.21) (2019-11-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.19...@patternfly/react-catalog-view-extension@1.1.20) (2019-11-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.18...@patternfly/react-catalog-view-extension@1.1.19) (2019-11-15) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.17...@patternfly/react-catalog-view-extension@1.1.18) (2019-11-14) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.16...@patternfly/react-catalog-view-extension@1.1.17) (2019-11-12) - - -### Bug Fixes - -* **CatalogTile:** Edit target selector ([#3291](https://github.com/patternfly/patternfly-react/issues/3291)) ([16bf30c](https://github.com/patternfly/patternfly-react/commit/16bf30c1fba9b4573688434cfb8fd65288709d02)) - - - - - -## [1.1.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.15...@patternfly/react-catalog-view-extension@1.1.16) (2019-11-08) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.14...@patternfly/react-catalog-view-extension@1.1.15) (2019-11-08) - - -### Bug Fixes - -* **CatalogTile:** Removed margin and fixed hidden text ([#3285](https://github.com/patternfly/patternfly-react/issues/3285)) ([4028a8c](https://github.com/patternfly/patternfly-react/commit/4028a8c3f7c696fc278f65360a538800ca3a8d0a)) - - - - - -## [1.1.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.13...@patternfly/react-catalog-view-extension@1.1.14) (2019-11-07) - - -### Bug Fixes - -* **react-catalog-view-extension:** fix checbox margin on filter side panel ([#3287](https://github.com/patternfly/patternfly-react/issues/3287)) ([895386b](https://github.com/patternfly/patternfly-react/commit/895386b2603ba291295743f50e3a72b796dfe167)) - - - - - -## [1.1.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.12...@patternfly/react-catalog-view-extension@1.1.13) (2019-11-07) - - -### Bug Fixes - -* **react-catalog-extension:** fix [@types](https://github.com/types) errors when using the extension ([#3284](https://github.com/patternfly/patternfly-react/issues/3284)) ([eda18c1](https://github.com/patternfly/patternfly-react/commit/eda18c1b171ac69c8c8a67227e8b994c8bc6b44d)) - - - - - -## [1.1.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.11...@patternfly/react-catalog-view-extension@1.1.12) (2019-11-07) - - -### Bug Fixes - -* **CatalogTile:** Update scss and add class to image ([#3282](https://github.com/patternfly/patternfly-react/issues/3282)) ([25e6f79](https://github.com/patternfly/patternfly-react/commit/25e6f792d0d0776d1bc0685bd3670308c79f54d6)) - - - - - -## [1.1.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.10...@patternfly/react-catalog-view-extension@1.1.11) (2019-11-07) - - -### Bug Fixes - -* **catalog-view-extension:** Remove unused dev dependencies from package.json ([#3275](https://github.com/patternfly/patternfly-react/issues/3275)) ([e74587f](https://github.com/patternfly/patternfly-react/commit/e74587f74e58e1bb10213d497be34fba1938dc2d)) - - - - - -## [1.1.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.9...@patternfly/react-catalog-view-extension@1.1.10) (2019-11-06) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.8...@patternfly/react-catalog-view-extension@1.1.9) (2019-11-06) - - -### Bug Fixes - -* **catalog-view-extension:** check for sass changes ([#3271](https://github.com/patternfly/patternfly-react/issues/3271)) ([3efa4e3](https://github.com/patternfly/patternfly-react/commit/3efa4e33658ce69e64ecb74d4365536856bbfb85)) - - - - - -## [1.1.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.7...@patternfly/react-catalog-view-extension@1.1.8) (2019-11-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.6...@patternfly/react-catalog-view-extension@1.1.7) (2019-11-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.5...@patternfly/react-catalog-view-extension@1.1.6) (2019-11-05) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.4...@patternfly/react-catalog-view-extension@1.1.5) (2019-11-01) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.3...@patternfly/react-catalog-view-extension@1.1.4) (2019-10-31) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.2...@patternfly/react-catalog-view-extension@1.1.3) (2019-10-30) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.1...@patternfly/react-catalog-view-extension@1.1.2) (2019-10-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -## [1.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-catalog-view-extension@1.1.0...@patternfly/react-catalog-view-extension@1.1.1) (2019-10-25) - -**Note:** Version bump only for package @patternfly/react-catalog-view-extension - - - - - -# 1.1.0 (2019-10-24) - - -### Features - -* **react-catalog-view-extension:** Added catalog view extension and three components ([#3145](https://github.com/patternfly/patternfly-react/issues/3145)) ([20a981b](https://github.com/patternfly/patternfly-react/commit/20a981b6aff0bbf3ff04d5b016f67bf76545f3cd)), closes [#3159](https://github.com/patternfly/patternfly-react/issues/3159) - - - - - -## 1.0.1 (2019-10-11) - -**Note:** Added catalog item header component diff --git a/packages/react-catalog-view-extension/README.md b/packages/react-catalog-view-extension/README.md deleted file mode 100644 index fb2b851c40d..00000000000 --- a/packages/react-catalog-view-extension/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# patternfly-catalog-view-extension - -This package contains catalog components based on the ones in PF3's patternfly-react-extensions package. - -This package is currently an extension. Extension components do not undergo the same rigorous design or coding review process as core PatternFly components. If enough members of the community find them useful, we will work to move them into our core PatternFly system by starting the design process for the idea. - -### Installing - -``` -yarn add react-catalog-view-extension -``` - -or - -``` -npm install react-catalog-view-extension --save -``` - -### Usage - -``` -import { Component } from 'react-catalog-view-extension'; -``` - -#### Styling: - -Example with SCSS: - -``` -@import "~patternfly-react/dist/sass/patternfly-react"; -@import "~react-catalog-view-extension/dist/sass/react-catalog-view-extension"; -``` - -### Building - -``` -yarn build -``` - -Note the build scripts for this are located in the root package.json under `yarn build`. - -### Testing - -Testing is done at the root of this repo. - -``` -yarn test -``` - -### Publishing - -``` -yarn publish -``` - diff --git a/packages/react-catalog-view-extension/buildSass.js b/packages/react-catalog-view-extension/buildSass.js deleted file mode 100644 index b8035a2f859..00000000000 --- a/packages/react-catalog-view-extension/buildSass.js +++ /dev/null @@ -1,32 +0,0 @@ -const path = require('path'); -const sass = require('sass'); -const fs = require('fs'); - -const outDir = 'dist/css'; - -/** - * @param {string} url - Url string - */ -function importer(url) { - // Assume yarn hoists these. - if (url.startsWith('patternfly')) { - url = path.join(__dirname, `../../node_modules/patternfly/dist/sass/${url}`); - } else if (url.startsWith('font-awesome')) { - // font-awesome is for pf3 docs - url = path.join(__dirname, `../../node_modules/font-awesome/scss/${url}`); - } else if (url.startsWith('~')) { - url = path.join(__dirname, `../../node_modules/${url.substr(1)}`); - } - return { file: url }; -} - -const res = sass.renderSync({ - file: 'sass/react-catalog-view-extension.scss', - outputStyle: 'compressed', - importer -}); -if (!fs.existsSync(outDir)) { - fs.mkdirSync(outDir); -} - -fs.writeFileSync(path.join(outDir, 'react-catalog-view-extension.css'), res.css); diff --git a/packages/react-catalog-view-extension/package.json b/packages/react-catalog-view-extension/package.json deleted file mode 100644 index 797c108df72..00000000000 --- a/packages/react-catalog-view-extension/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "@patternfly/react-catalog-view-extension", - "version": "4.39.0", - "description": "This library provides catalog view extensions for PatternFly 4 React.", - "main": "dist/js/index.js", - "module": "dist/esm/index.js", - "types": "dist/esm/index.d.ts", - "patternfly:src": "src/", - "sideEffects": [ - "*.css", - "*.scss" - ], - "publishConfig": { - "access": "public", - "tag": "prerelease" - }, - "repository": { - "type": "git", - "url": "https://github.com/patternfly/patternfly-react.git" - }, - "keywords": [ - "react", - "patternfly" - ], - "author": "Red Hat", - "license": "MIT", - "bugs": { - "url": "https://github.com/patternfly/patternfly-react/issues" - }, - "homepage": "https://github.com/patternfly/patternfly-react/blob/main/packages/react-catalog-view-extension/README.md", - "scripts": { - "generate": "concurrently \"yarn build:sass\" \"yarn copy:sass\"", - "build:sass": "node buildSass.js", - "copy:sass": "shx mkdir -p dist/sass && shx cp -r sass/react-catalog-view-extension/* dist/sass", - "clean": "rimraf dist" - }, - "dependencies": { - "@patternfly/patternfly": "4.166.4", - "@patternfly/react-core": "^4.188.0", - "@patternfly/react-styles": "^4.38.0" - }, - "devDependencies": { - "concurrently": "^5.3.0", - "rimraf": "^2.6.2", - "sass": "^1.42.1", - "shx": "^0.3.2", - "tslib": "^2.0.0", - "typescript": "^4.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - } -} diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension.scss deleted file mode 100644 index 80b253d14b7..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension.scss +++ /dev/null @@ -1,5 +0,0 @@ -// Patternfly Core variables -@import "~@patternfly/patternfly/sass-utilities/colors"; - -// Extensions StyleSheets -@import './react-catalog-view-extension/react-catalog-view-extension'; diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_catalog-item.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_catalog-item.scss deleted file mode 100644 index d5c3efcf880..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_catalog-item.scss +++ /dev/null @@ -1,25 +0,0 @@ -.catalog-item-header-pf { - display: flex; - align-items: center; -} - -.catalog-item-header-pf-icon { - font-size: 60px; - max-height: 60px; - width: 60px; -} - -.catalog-item-header-pf-text { - margin-left: 20px; -} - -.catalog-item-header-pf-title { - font-weight: 400; - margin-bottom: 0; - margin-top: 0; -} - -.catalog-item-header-pf-subtitle { - color: $pf-color-black-500; - margin-bottom: 0; -} diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_catalog-tile.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_catalog-tile.scss deleted file mode 100644 index 67dfbeffa20..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_catalog-tile.scss +++ /dev/null @@ -1,77 +0,0 @@ -.catalog-tile-pf { - &.featured { - border-top: 2px solid $pf-color-blue-300; - } - - &:active, - &:hover, - &:focus, - &:visited { - color: inherit; - text-decoration: none; - } - - .pf-c-card__actions { - padding-left: 5px; - } -} - -.catalog-tile-pf-header { - font-size: 16px; - font-weight: 400; - padding-bottom: 16px; - - .catalog-tile-pf-title { - font-size: 15px; - font-weight: 400; - } - - .catalog-tile-pf-subtitle { - color: $pf-color-black-500; - font-size: 13px; - font-weight: initial; - - a { - color: $pf-color-blue-300; - text-decoration: none; - } - - a:hover { - color: $pf-color-blue-200; - text-decoration: none; - } - } -} - -.catalog-tile-pf-icon { - font-size: 40px; - height: 40px; - max-width: 60px; - min-width: 40px; -} - -.catalog-tile-pf-badge-container { - display: flex; - flex: 1; - justify-content: flex-end; - - .catalog-tile-pf-badge { - font-size: 16px; - margin-left: 5px; - } -} - -.catalog-tile-pf-description { - margin-top: 0; - - span { - display: -webkit-box; - overflow: hidden; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - } - - .has-footer { - -webkit-line-clamp: 1; - } -} diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_filter-side-panel.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_filter-side-panel.scss deleted file mode 100644 index 9e488cf7fbd..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_filter-side-panel.scss +++ /dev/null @@ -1,44 +0,0 @@ -.filter-panel-pf { - margin: 0 0 30px; - padding: 0 15px; -} - -.filter-panel-pf-category { - margin-top: 20px; - - &:first-of-type { - margin-top: 0; - } -} - -.filter-panel-pf-category-title { - border: 0; - font-size: inherit; - margin: 0; - font-weight: 700; -} - -.filter-panel-pf-category-items { - margin-top: 0; - margin-bottom: 0; -} - -.filter-panel-pf-category-item { - margin-top: 5px; - - &:first-of-type { - margin-top: 0; - } - - .pf-c-check__label { - min-height: 23px; - } - - .item-icon { - padding-right: 3px; - } - - .item-count { - padding-left: 3px; - } -} diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_properties-side-panel.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_properties-side-panel.scss deleted file mode 100644 index 707b47a2664..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_properties-side-panel.scss +++ /dev/null @@ -1,23 +0,0 @@ -.properties-side-panel-pf { - width: 165px; -} - -.properties-side-panel-pf-property { - margin-top: 24px; - - &:first-of-type { - margin-top: 0; - } -} - -.properties-side-panel-pf-property-label { - font-weight: 700 !important; - font-size: 14px !important; - margin: 0 !important; -} - -.properties-side-panel-pf-property-value { - font-size: 14px !important; - margin-top: 8px; - word-break: break-word; -} diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_react-catalog-view-extension.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_react-catalog-view-extension.scss deleted file mode 100644 index 636803775c3..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_react-catalog-view-extension.scss +++ /dev/null @@ -1,9 +0,0 @@ -/** - Patternfly React Extensions Partials -*/ -@import 'variables'; -@import 'catalog-item'; -@import 'catalog-tile'; -@import 'vertical-tabs'; -@import 'properties-side-panel'; -@import 'filter-side-panel'; diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_variables.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_variables.scss deleted file mode 100644 index 0338c6dd494..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_variables.scss +++ /dev/null @@ -1,2 +0,0 @@ -$vertical-tab-pf-color: initial; -$vertical-tab-pf-active-color: $pf-color-blue-400; diff --git a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_vertical-tabs.scss b/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_vertical-tabs.scss deleted file mode 100644 index ad9c3e2ebdf..00000000000 --- a/packages/react-catalog-view-extension/sass/react-catalog-view-extension/_vertical-tabs.scss +++ /dev/null @@ -1,95 +0,0 @@ -.vertical-tabs-pf { - list-style: none; - margin: 0 0 30px; - padding: 0; - - .vertical-tabs-pf { - margin-bottom: 0; - } -} - -.vertical-tabs-pf-tab { - margin-top: 4px; - position: relative; - - > a { - color: $vertical-tab-pf-color; - display: inline-block; - font-size: 13px; - padding: 3px 6px 3px 15px; - vertical-align: top; - width: 100%; - word-break: break-word; - - &:hover, - &:focus { - color: $vertical-tab-pf-active-color; - text-decoration: none; - } - - &.no-wrap { - overflow-x: hidden; - white-space: nowrap; - } - - &.truncate { - overflow-x: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - } - - &.active { - > a { - color: $vertical-tab-pf-active-color; - - &::before { - background: $vertical-tab-pf-active-color; - content: "\00a0"; //   - left: 0; - position: absolute; - width: 3px; - } - } - } - - &:first-of-type { - margin-top: 0; - } - - > .vertical-tabs-pf { - > .vertical-tabs-pf-tab { - position: initial; - padding-left: 15px; - } - } -} - -.vertical-tabs-pf.restrict-tabs { - .vertical-tabs-pf-tab { - display: none; - - /* Show any active tab, tab that has an active descendant, or is force shown */ - &.active, - &.active-descendant, - &.shown { - display: block; - } - } - - /* Show siblings of the active tab */ - &.active-tab { - > .vertical-tabs-pf-tab { - display: block; - } - } - - /* Show the direct children of an active tab */ - .vertical-tabs-pf-tab.active { - > .vertical-tabs-pf { - > .vertical-tabs-pf-tab { - display: block; - } - } - } -} diff --git a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/CatalogItemHeader.test.tsx b/packages/react-catalog-view-extension/src/components/CatalogItemHeader/CatalogItemHeader.test.tsx deleted file mode 100644 index 756fde4e3b7..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/CatalogItemHeader.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { CatalogItemHeader } from './CatalogItemHeader'; -import React from 'react'; -import { shallow } from 'enzyme'; - -test('simple catalog item header', () => { - const view = shallow( - - provided by Red Hat - - } - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/CatalogItemHeader.tsx b/packages/react-catalog-view-extension/src/components/CatalogItemHeader/CatalogItemHeader.tsx deleted file mode 100644 index fa483da9397..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/CatalogItemHeader.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -export interface CatalogItemHeaderProps extends Omit, 'title'> { - /** Additional css classes */ - className?: string; - /** URL of an image for the item's icon */ - iconImg?: string; - /** Class for the image when an icon is to be used (exclusive from iconImg) */ - iconClass?: string; - /** Tile for the catalog item */ - title: string | React.ReactNode; - /** Vendor for the catalog item */ - vendor?: string | React.ReactNode; -} - -export const CatalogItemHeader: React.FunctionComponent = ({ - className = '', - iconImg = null, - iconClass = null, - title, - vendor = null, - ...props -}: CatalogItemHeaderProps) => ( -
- {iconImg && } - {!iconImg && iconClass && } -
-

{title}

- {vendor &&
{vendor}
} -
-
-); -CatalogItemHeader.displayName = 'CatalogItemHeader'; diff --git a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/__snapshots__/CatalogItemHeader.test.tsx.snap b/packages/react-catalog-view-extension/src/components/CatalogItemHeader/__snapshots__/CatalogItemHeader.test.tsx.snap deleted file mode 100644 index 3ac2127d854..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/__snapshots__/CatalogItemHeader.test.tsx.snap +++ /dev/null @@ -1,29 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`simple catalog item header 1`] = ` -
-
-

- PatternFly -

-
- - provided by - - Red Hat - - -
-
-
-`; diff --git a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/CatalogItemHeader.md b/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/CatalogItemHeader.md deleted file mode 100644 index 798438c07cd..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/CatalogItemHeader.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: Catalog view item header -section: extensions -propComponents: ['CatalogItemHeader'] ---- - -import { CatalogItemHeader } from '@patternfly/react-catalog-view-extension'; -import pfLogo2 from './pfLogo2.svg'; -import './catalogItemHeader.css'; - -## Introduction -Note: Catalog item header lives in its own package at [`@patternfly/react-catalog-view-extension`](https://www.npmjs.com/package/@patternfly/react-catalog-view-extension)! - -This package is currently an extension. Extension components do not undergo the same rigorous design or coding review process as core PatternFly components. If enough members of the community find them useful, we will work to move them into our core PatternFly system by starting the design process for the idea. - -## Examples -### Basic -```js -import React from 'react'; -import { CatalogItemHeader } from '@patternfly/react-catalog-view-extension'; -import pfLogo2 from './examples/pfLogo2.svg'; - - -``` - -### With vendor description -```js -import React from 'react'; -import { CatalogItemHeader } from '@patternfly/react-catalog-view-extension'; -import pfLogo2 from './examples/pfLogo2.svg'; - - - provided by Red Hat - - } -/> -``` diff --git a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/catalogItemHeader.css b/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/catalogItemHeader.css deleted file mode 100644 index a381f8f308a..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/catalogItemHeader.css +++ /dev/null @@ -1,28 +0,0 @@ -.ws-react-e-catalog-view-item-header .text-overflow-pf { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - word-wrap: normal; -} -.ws-react-e-catalog-view-item-header .catalog-item-header-pf { - display: flex; - align-items: center; -} -.ws-react-e-catalog-view-item-header .catalog-item-header-pf-icon { - font-size: 60px; - max-height: 60px; - width: 60px; -} -.ws-react-e-catalog-view-item-header .catalog-item-header-pf-text { - margin-left: 20px; -} -.ws-react-e-catalog-view-item-header .catalog-item-header-pf-title { - font-weight: 400; - margin-bottom: 0; - margin-top: 0; -} -.ws-react-e-catalog-view-item-header .catalog-item-header-pf-subtitle { - color: #8b8d8f; - font-size: small; - margin-bottom: 0; -} diff --git a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/pfLogo2.svg b/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/pfLogo2.svg deleted file mode 100644 index 748d64a6519..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/examples/pfLogo2.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/index.ts b/packages/react-catalog-view-extension/src/components/CatalogItemHeader/index.ts deleted file mode 100644 index 8cd9fb42df2..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogItemHeader/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './CatalogItemHeader'; diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTile.test.tsx b/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTile.test.tsx deleted file mode 100644 index 4bddc8267bb..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTile.test.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import * as React from 'react'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import OutlinedCheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/outlined-check-circle-icon'; -import { mount } from 'enzyme'; - -import { CatalogTile } from './CatalogTile'; -import { CatalogTileBadge } from './CatalogTileBadge'; - -test('CatalogTile renders properly', () => { - const component = mount( -
- - - , - - - - ]} - title="Patternfly" - vendor={ - - Provided by Red Hat - - } - description="A community of designers and developers collaborating to build a UI framework for enterprise web applications." - /> - - - , - - - - ]} - title="GitHub Desktop" - vendor="provided by GitHub" - description="Simple collaboration from your desktop." - /> - - - - ]} - title="CodePen" - vendor="provided by CodePen" - description="An online community for testing and showcasing user-created HTML, CSS and JavaScript code snippets." - /> - - - - ]} - title="Patternfly-React" - vendor="provided by Red Hat" - description="1234567890123" - footer={ - - Enabled - - } - /> - - - - } - /> -
- ); - expect(component).toMatchSnapshot(); -}); - -test('CatalogTile href renders properly', () => { - const view = mount( - - ); - expect(view).toMatchSnapshot(); -}); - -test('CatalogTile onClick behaves properly', () => { - const onClickMock = jest.fn(); - - const view = mount( - - ); - - view - .find('#test-on-click.test-click-class') - .hostNodes() - .simulate('click'); - expect(onClickMock).toBeCalled(); -}); diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTile.tsx b/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTile.tsx deleted file mode 100644 index 08ff6096a61..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTile.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import * as React from 'react'; -import { Card, CardActions, CardHeader, CardTitle, CardBody, CardFooter } from '@patternfly/react-core'; -import { css } from '@patternfly/react-styles'; - -export interface CatalogTileProps extends Omit, 'title'> { - /** Id */ - id?: any; - /** Additional css classes */ - className?: string; - /** Flag if the tile is 'featured' */ - featured: boolean; - /** Callback for a click on the tile */ - onClick?: (event: React.SyntheticEvent) => void; - /** href for the tile if used as a link */ - href: string; - /** URL of an image for the item's icon */ - iconImg?: string; - /** Alternate text for the item's icon */ - iconAlt?: string; - /** Class for the image when an icon is to be used (exclusive from iconImg) */ - iconClass?: string; - /** Alternatively provided JSX for the icon */ - icon?: React.ReactNode; - /** Array of badges */ - badges?: React.ReactNode[]; - /** Tile for the catalog item */ - title: string | React.ReactNode; - /** Vendor for the catalog item */ - vendor?: string | React.ReactNode; - /** Description of the catalog item */ - description?: string | React.ReactNode; - /** Footer for the tile */ - footer?: string | React.ReactNode; - /** Body content that isn't truncated */ - children?: React.ReactNode; -} - -export class CatalogTile extends React.Component { - static displayName = 'CatalogTile'; - static defaultProps = { - id: null as any, - className: '', - featured: false, - onClick: null as (event: React.SyntheticEvent) => void, - href: null as string, - iconImg: null as string, - iconAlt: '', - iconClass: '', - icon: null as React.ReactNode, - badges: [] as React.ReactNode[], - vendor: null as string | React.ReactNode, - description: null as string | React.ReactNode, - footer: null as string | React.ReactNode, - children: null as React.ReactNode - }; - - private handleClick = (e: React.SyntheticEvent) => { - const { onClick, href } = this.props; - - if (!href) { - e.preventDefault(); - } - if (onClick) { - onClick(e); - } - }; - - private renderBadges = (badges: React.ReactNode[]) => { - if (!badges || !badges.length) { - return null; - } - - return ( -
- {badges.map((badge, index) => ( - {badge} - ))} -
- ); - }; - - render() { - const { - id, - className, - featured, - onClick, - href, - icon, - iconImg, - iconAlt, - iconClass, - badges, - title, - vendor, - description, - footer, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, - children, - ...props - } = this.props; - - return ( - this.handleClick(e)} - isSelectable - {...props} - > - {(badges.length > 0 || iconImg || iconClass || icon) && ( - - {iconImg && {iconAlt}} - {!iconImg && (iconClass || icon) && {icon}} - {badges.length > 0 && {this.renderBadges(badges)}} - - )} - -
{title}
- {vendor &&
{vendor}
} -
- {(description || children) && ( - - {description && ( -
- {description} -
- )} - {children} -
- )} - {footer && {footer}} -
- ); - } -} diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTileBadge.tsx b/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTileBadge.tsx deleted file mode 100644 index c486ed08a36..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/CatalogTileBadge.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from 'react'; -import { Tooltip } from '@patternfly/react-core'; -import { css } from '@patternfly/react-styles'; - -export interface CatalogTileBadgeProps extends Omit, 'title'> { - /** Children (typically an Icon) */ - children?: React.ReactNode; - /** Additional css classes */ - className?: string; - /** Id (was necessary for PF3 tooltip, but not for the PF4 one; keeping prop in case people still want it) */ - id?: string; - /** Tooltip String (also used for screen readers) */ - title?: string; -} - -export const CatalogTileBadge: React.FunctionComponent = ({ - children = null, - className = '', - id = null, - title = null, - ...props -}: CatalogTileBadgeProps) => { - const classes = css('catalog-tile-pf-badge', className); - - if (title) { - return ( - - - - {children} - {title} - - - - ); - } - return ( - - {children} - - ); -}; -CatalogTileBadge.displayName = 'CatalogTileBadge'; diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/__snapshots__/CatalogTile.test.tsx.snap b/packages/react-catalog-view-extension/src/components/CatalogTile/__snapshots__/CatalogTile.test.tsx.snap deleted file mode 100644 index 809c3f5a38d..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/__snapshots__/CatalogTile.test.tsx.snap +++ /dev/null @@ -1,1316 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CatalogTile href renders properly 1`] = ` - - - - -
-
- Patternfly -
-
- Provided by Red Hat -
-
-
- -
-
- - 1234567890123 - -
-
-
-
-
-
-`; - -exports[`CatalogTile renders properly 1`] = ` -
- - - , - - - , - ] - } - className="" - description="A community of designers and developers collaborating to build a UI framework for enterprise web applications." - featured={true} - footer={null} - href={null} - icon={null} - iconAlt="" - iconClass="" - iconImg={null} - id="single-badge-test" - onClick={null} - title="Patternfly" - vendor={ - - Provided by - - Red Hat - - - } - > - -
- -
- -
-
- - - - - - - Certified - -
- } - popperMatchesTriggerWidth={false} - positionModifiers={ - Object { - "bottom": "pf-m-bottom", - "left": "pf-m-left", - "right": "pf-m-right", - "top": "pf-m-top", - } - } - trigger={ - - - - Certified - - - } - zIndex={9999} - > - - - - - - - - - Certified - - - - - - - - - - - - - - - - - - -
-
- -
- - -
-
- Patternfly -
-
- - Provided by - - Red Hat - - -
-
-
- -
-
- - A community of designers and developers collaborating to build a UI framework for enterprise web applications. - -
-
-
-
- -
- - - , - - - , - ] - } - className="" - description="Simple collaboration from your desktop." - featured={false} - footer={null} - href={null} - icon={null} - iconAlt="" - iconClass="" - iconImg={null} - id="multi-badge-test" - onClick={null} - title="GitHub Desktop" - vendor="provided by GitHub" - > - -
- -
- -
-
- - - - - - - Certified - -
- } - popperMatchesTriggerWidth={false} - positionModifiers={ - Object { - "bottom": "pf-m-bottom", - "left": "pf-m-left", - "right": "pf-m-right", - "top": "pf-m-top", - } - } - trigger={ - - - - Certified - - - } - zIndex={9999} - > - - - - - - - - - Certified - - - - - - - - - - - - - - USDA Approved - -
- } - popperMatchesTriggerWidth={false} - positionModifiers={ - Object { - "bottom": "pf-m-bottom", - "left": "pf-m-left", - "right": "pf-m-right", - "top": "pf-m-top", - } - } - trigger={ - - - - USDA Approved - - - } - zIndex={9999} - > - - - - - - - - - USDA Approved - - - - - - - -
-
- - - - -
-
- GitHub Desktop -
-
- provided by GitHub -
-
-
- -
-
- - Simple collaboration from your desktop. - -
-
-
- -
-
- - - , - ] - } - className="" - description="An online community for testing and showcasing user-created HTML, CSS and JavaScript code snippets." - featured={false} - footer={null} - href={null} - icon={null} - iconAlt="" - iconClass="fa fa-codepen" - iconImg={null} - id="test-iconClass" - onClick={null} - title="CodePen" - vendor="provided by CodePen" - > - -
- -
- - -
-
- - - - - - - USDA Approved - -
- } - popperMatchesTriggerWidth={false} - positionModifiers={ - Object { - "bottom": "pf-m-bottom", - "left": "pf-m-left", - "right": "pf-m-right", - "top": "pf-m-top", - } - } - trigger={ - - - - USDA Approved - - - } - zIndex={9999} - > - - - - - - - - - USDA Approved - - - - - - - -
-
- -
- - -
-
- CodePen -
-
- provided by CodePen -
-
-
- -
-
- - An online community for testing and showcasing user-created HTML, CSS and JavaScript code snippets. - -
-
-
- -
-
- - - , - ] - } - className="" - description="1234567890123" - featured={true} - footer={ - - - Enabled - - } - href="https://github.com/patternfly/patternfly-react" - icon={null} - iconAlt="" - iconClass="" - iconImg={null} - id="tile-footer-test" - onClick={null} - title="Patternfly-React" - vendor="provided by Red Hat" - > - - - -
- -
-
- - - - - - - Certified - -
- } - popperMatchesTriggerWidth={false} - positionModifiers={ - Object { - "bottom": "pf-m-bottom", - "left": "pf-m-left", - "right": "pf-m-right", - "top": "pf-m-top", - } - } - trigger={ - - - - Certified - - - } - zIndex={9999} - > - - - - - - - - - Certified - - - - - - - -
-
- - -
- -
-
- Patternfly-React -
-
- provided by Red Hat -
-
-
- -
-
- - 1234567890123 - -
-
-
- -
- - - - - - - Enabled - -
-
-
-
-
- - - - } - iconAlt="" - iconClass="" - iconImg={null} - id="custom-icon-svg-test" - onClick={null} - title="Custom SVG" - vendor={null} - > - - - -
- - - - - -
-
- -
-
- Custom SVG -
-
-
-
-
-
- -`; diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/examples/CatalogTile.md b/packages/react-catalog-view-extension/src/components/CatalogTile/examples/CatalogTile.md deleted file mode 100644 index a40c31359ce..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/examples/CatalogTile.md +++ /dev/null @@ -1,185 +0,0 @@ ---- -id: Catalog view tile -section: extensions -propComponents: ['CatalogTile'] ---- - -import { CatalogTile, CatalogTileBadge } from '@patternfly/react-catalog-view-extension'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import OutlinedCheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/outlined-check-circle-icon'; -import pfLogo2 from './pfLogo2.svg'; -import './catalogTile.css'; - -## Introduction - -Note: Catalog tile lives in its own package at [`@patternfly/react-catalog-view-extension`](https://www.npmjs.com/package/@patternfly/react-catalog-view-extension)! - -This package is currently an extension. Extension components do not undergo the same rigorous design or coding review process as core PatternFly components. If enough members of the community find them useful, we will work to move them into our core PatternFly system by starting the design process for the idea. - -## Examples -### Basic featured tile -```js -import React from 'react'; -import { CatalogTile, CatalogTileBadge } from '@patternfly/react-catalog-view-extension'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import pfLogo2 from './pfLogo2.svg'; - - - - - ]} - title="Patternfly-React" - vendor="provided by Red Hat" - description={ - 'This is a very, very long description that should be truncated after three lines. ' + - 'Three lines is the default for cards without a footer. Cards with a footer are truncated after one line. Truncation function use is deprecated; please pass in a maxDescriptionLength of -1 to override it. ' + - 'This has changed from PatternFly 3.' - } -/> -``` - -### Basic with footer -```js -import React from 'react'; -import { CatalogTile, CatalogTileBadge } from '@patternfly/react-catalog-view-extension'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import OutlinedCheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/outlined-check-circle-icon'; -import pfLogo2 from './pfLogo2.svg'; - - - - - ]} - title="Patternfly-React" - vendor="provided by Red Hat" - description={ - 'This is a very, very long description that should be truncated after one line. ' + - 'Three lines is the default for cards without a footer. Cards with a footer are truncated after one line. Truncation function use is deprecated; please pass in a maxDescriptionLength of -1 to override it. ' + - 'This has changed from PatternFly 3.' - } - footer={ - - Enabled - - } -/> -``` - -### Link variant -```js -import React from 'react'; -import { CatalogTile, CatalogTileBadge } from '@patternfly/react-catalog-view-extension'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import pfLogo2 from './pfLogo2.svg'; - - - - - ]} - href="http://patternfly.org/v4" - title="Patternfly-React" - vendor="provided by Red Hat" - description={ - 'This is a very, very long description that should be truncated after three lines. ' + - 'Three lines is the default for cards without a footer. Cards with a footer are truncated after one line. Truncation function use is deprecated; please pass in a maxDescriptionLength of -1 to override it. ' + - 'This has changed from PatternFly 3.' - } -/> -``` - -### With multiple icon badges -```js -import React from 'react'; -import { CatalogTile, CatalogTileBadge } from '@patternfly/react-catalog-view-extension'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import OutlinedCheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/outlined-check-circle-icon'; -import pfLogo2 from './pfLogo2.svg'; - - - - , - - - - ]} - title="Patternfly-React" - vendor={provided by Red Hat} - description={ - 'This is a very, very long description that should be truncated after three lines. ' + - 'Three lines is the default for cards without a footer. Cards with a footer are truncated after one line. Truncation function use is deprecated; please pass in a maxDescriptionLength of -1 to override it. ' + - 'This has changed from PatternFly 3.' - } -/> -``` - -### With text badge -```js -import React from 'react'; -import { CatalogTile } from '@patternfly/react-catalog-view-extension'; -import pfLogo2 from './pfLogo2.svg'; - -provided by Red Hat} - description={ - 'This is a very, very long description that should be truncated after three lines. ' + - 'Three lines is the default for cards without a footer. Cards with a footer are truncated after one line. Truncation function use is deprecated; please pass in a maxDescriptionLength of -1 to override it. ' + - 'This has changed from PatternFly 3.' - } -/> -``` - -### With children instead of description -```js -import React from 'react'; -import { CatalogTile, CatalogTileBadge } from '@patternfly/react-catalog-view-extension'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import pfLogo2 from './pfLogo2.svg'; - - - - - ]} - title="Patternfly-React" - vendor="provided by Red Hat" -> - This is a very, very long stetch of child text that should be not be truncated - and illustrates how Flyers can add longer content to PatternFly 4 catalog tiles - using the children prop. Cards usually truncate descriptions at three lines. - Cards with a footer are truncated after one line. This has changed from PatternFly 3. - Children can be of any length. - -``` diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/examples/catalogTile.css b/packages/react-catalog-view-extension/src/components/CatalogTile/examples/catalogTile.css deleted file mode 100644 index 0a551eb8e91..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/examples/catalogTile.css +++ /dev/null @@ -1,57 +0,0 @@ -.ws-react-e-catalog-view-tile .catalog-tile-pf.featured { - border-top: 2px solid #39a5dc; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf:active, .ws-react-e-catalog-view-tile .catalog-tile-pf:hover, .ws-react-e-catalog-view-tile .catalog-tile-pf:focus, .ws-react-e-catalog-view-tile .catalog-tile-pf:visited { - color: inherit; - text-decoration: none; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-header { - font-size: 16px; - font-weight: 400; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-header .catalog-tile-pf-title { - font-weight: 400; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-header .catalog-tile-pf-subtitle { - color: #4D5258; - font-size: small; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-header .catalog-tile-pf-subtitle a { - color: #0066CC; - text-decoration: none; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-header .catalog-tile-pf-subtitle a:hover { - color: #004080; - text-decoration: underline; -} -.ws-react-e-catalog-view-tile .pf-c-card__actions { - padding-left: 5px; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-icon { - font-size: 40px; - height: 40px; - max-width: 60px; - min-width: 40px; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-badge-container { - display: flex; - flex: 1; - justify-content: flex-end; - margin-left: 10px; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-badge-container .catalog-tile-pf-badge { - font-size: 16px; - margin-left: 5px; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-body .catalog-tile-pf-description span { - display: -webkit-box; - overflow: hidden; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; -} -.ws-react-e-catalog-view-tile .catalog-tile-pf-body .catalog-tile-pf-description span.has-footer { - -webkit-line-clamp: 1; -} -.ws-react-e-catalog-view-tile .example-ok-icon { - color: #4CB140; -} diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/examples/pfLogo2.svg b/packages/react-catalog-view-extension/src/components/CatalogTile/examples/pfLogo2.svg deleted file mode 100644 index 748d64a6519..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/examples/pfLogo2.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/packages/react-catalog-view-extension/src/components/CatalogTile/index.ts b/packages/react-catalog-view-extension/src/components/CatalogTile/index.ts deleted file mode 100644 index ffe99337086..00000000000 --- a/packages/react-catalog-view-extension/src/components/CatalogTile/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './CatalogTile'; -export * from './CatalogTileBadge'; diff --git a/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanel.tsx b/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanel.tsx deleted file mode 100644 index bc732a656fa..00000000000 --- a/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanel.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -export interface FilterSidePanelProps extends React.HTMLProps { - /** Children nodes */ - children: React.ReactNode; - /** Additional css classes for the Filter Side Panel */ - className?: string; -} - -export const FilterSidePanel: React.FunctionComponent = ({ - children = null, - className = '', - ...props -}: FilterSidePanelProps) => { - const classes = css('filter-panel-pf', className); - return ( -
- {children} -
- ); -}; -FilterSidePanel.displayName = 'FilterSidePanel'; - -export default FilterSidePanel; diff --git a/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanelCategory.tsx b/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanelCategory.tsx deleted file mode 100644 index 3b32a22e7f3..00000000000 --- a/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanelCategory.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import * as React from 'react'; -import { Button } from '@patternfly/react-core'; -import formStyles from '@patternfly/react-styles/css/components/Form/form'; -import { css } from '@patternfly/react-styles'; - -import { childrenToArray } from '../../helpers/util'; - -export interface FilterSidePanelCategoryProps extends Omit, 'title'> { - /** Children nodes */ - children?: React.ReactNode; - /** Additional css classes for the Filter Side Panel Category */ - className?: string; - /** Title for the category */ - title?: string | React.ReactNode; - /** Number of items (max) to show before adding Show More link button */ - maxShowCount?: number; - /** Leeway to add to maxShowCount, minimum X for the 'Show X more' */ - leeway?: number; - /** Flag to show all items (ie. set to true after Show X more link is clicked) */ - showAll?: boolean; - /** Callback function when the Show/Hide link button is clicked */ - onShowAllToggle?: (event: React.SyntheticEvent) => void; - /** Text for the link to show all items, default 'Show more' */ - showText?: string; - /** Text for the link to hide overflow items, default 'Show less' */ - hideText?: string; -} - -export const FilterSidePanelCategory: React.FunctionComponent = ({ - children = null, - className = '', - title = null, - maxShowCount = 5, - leeway = 2, - showAll = false, - onShowAllToggle = () => null, - showText = null, - hideText = null, - ...props -}: FilterSidePanelCategoryProps) => { - const classes = css('filter-panel-pf-category', className); - const childrenArray = childrenToArray(children); - const itemCount = childrenArray.length; - const hiddenCount = itemCount - maxShowCount; - let shownChildren; - let showAllToggle = null; - - if (hiddenCount <= leeway || showAll) { - shownChildren = children; - if (hiddenCount > leeway) { - showAllToggle = ( - - ); - } - } else { - shownChildren = childrenArray.slice(0, maxShowCount); - if (hiddenCount > leeway) { - showAllToggle = ( - - ); - } - } - - return ( -
-
- {title && {title}} - {shownChildren} - {showAllToggle} -
-
- ); -}; -FilterSidePanelCategory.displayName = 'FilterSidePanelCategory'; - -export default FilterSidePanelCategory; diff --git a/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanelCategoryItem.tsx b/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanelCategoryItem.tsx deleted file mode 100644 index 5a67dda86b7..00000000000 --- a/packages/react-catalog-view-extension/src/components/FilterSidePanel/FilterSidePanelCategoryItem.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import { Checkbox } from '@patternfly/react-core'; - -import { getUniqueId } from '../../helpers/util'; - -export interface FilterSidePanelCategoryItemProps extends React.HTMLProps { - /** Children nodes */ - children?: React.ReactNode; - /** Additional css classes for the Filter Panel Property Item */ - className?: string; - /** Optional icon (or other) to show before the children */ - icon?: React.ReactNode; - /** Optional count of the items matching the filter */ - count?: number; - /** Callback for a click on the Filter Item Checkbox */ - onClick?: (event: React.SyntheticEvent) => void; - /** Flag to show if the Filter Item Checkbox is checked. */ - checked?: boolean; - /** Title of the checkbox */ - title?: string; -} - -export const FilterSidePanelCategoryItem: React.FunctionComponent = ({ - children = null, - className = '', - icon = null, - count = null, - onClick = null, - checked = false, - title = '', - ...props -}: FilterSidePanelCategoryItemProps) => { - const classes = css('filter-panel-pf-category-item', className); - const label = ( - - {icon && {icon}} - {children} - {Number.isInteger(count) && {`(${count})`}} - - ); - return ( -
- -
- ); -}; -FilterSidePanelCategoryItem.displayName = 'FilterSidePanelCategoryItem'; - -export default FilterSidePanelCategoryItem; diff --git a/packages/react-catalog-view-extension/src/components/FilterSidePanel/examples/FilterSidePanel.md b/packages/react-catalog-view-extension/src/components/FilterSidePanel/examples/FilterSidePanel.md deleted file mode 100644 index 72864ccf53d..00000000000 --- a/packages/react-catalog-view-extension/src/components/FilterSidePanel/examples/FilterSidePanel.md +++ /dev/null @@ -1,427 +0,0 @@ ---- -id: Catalog view filter side panel -section: extensions -propComponents: ['FilterSidePanel', 'FilterSidePanelCategory', 'FilterSidePanelCategoryItem'] ---- - -import { FilterSidePanel, FilterSidePanelCategory, FilterSidePanelCategoryItem } from '@patternfly/react-catalog-view-extension'; -import StarIcon from '@patternfly/react-icons/dist/esm/icons/star-icon'; -import CcPaypalIcon from '@patternfly/react-icons/dist/esm/icons/cc-paypal-icon'; -import CcAmexIcon from '@patternfly/react-icons/dist/esm/icons/cc-amex-icon'; -import CcDiscoverIcon from '@patternfly/react-icons/dist/esm/icons/cc-discover-icon'; -import CcVisaIcon from '@patternfly/react-icons/dist/esm/icons/cc-visa-icon'; -import CcMastercardIcon from '@patternfly/react-icons/dist/esm/icons/cc-mastercard-icon'; -import CcDinersClubIcon from '@patternfly/react-icons/dist/esm/icons/cc-diners-club-icon'; - -import './filterSidePanel.css'; - -## Introduction -Note: FilterSidePanel lives in its own package at [`@patternfly/react-catalog-view-extension`](https://www.npmjs.com/package/@patternfly/react-catalog-view-extension)! - -Note: the width, border, and top padding styling are not part of the FilterSidePanel. - -This package is currently an extension. Extension components do not undergo the same rigorous design or coding review process as core PatternFly components. If enough members of the community find them useful, we will work to move them into our core PatternFly system by starting the design process for the idea. - - -## Examples - -### Basic -```js -import React from 'react'; -import { FilterSidePanel, FilterSidePanelCategory, FilterSidePanelCategoryItem } from '@patternfly/react-catalog-view-extension'; -import StarIcon from '@patternfly/react-icons/dist/esm/icons/star-icon'; -import CcPaypalIcon from '@patternfly/react-icons/dist/esm/icons/cc-paypal-icon'; -import CcAmexIcon from '@patternfly/react-icons/dist/esm/icons/cc-amex-icon'; -import CcDiscoverIcon from '@patternfly/react-icons/dist/esm/icons/cc-discover-icon'; -import CcVisaIcon from '@patternfly/react-icons/dist/esm/icons/cc-visa-icon'; -import CcMastercardIcon from '@patternfly/react-icons/dist/esm/icons/cc-mastercard-icon'; -import CcDinersClubIcon from '@patternfly/react-icons/dist/esm/icons/cc-diners-club-icon'; -import { TextInput } from '@patternfly/react-core'; - -class MockFilterSidePanelExample extends React.Component { - constructor(props) { - super(props); - this.state = { - activeFilters: { - typeSUV: false, - typeSedan: false, - typePickup: false, - typeSports: false, - makeChevy: false, - makeFord: false, - makeDodge: false, - makeVolkswagen: false, - makeHyundai: false, - makeHonda: false, - makeToyota: false, - makeMercedes: false, - makeBMW: false, - makeInfiniti: false, - makeLexus: false, - makeAcura: false, - paymentPaypal: false, - paymentDiscover: false, - paymentVisa: false, - paymentMastercard: false, - paymentAmex: false, - paymentDinersClub: false, - mileage50: false, - mileage40: false, - mileage30: false, - mileage20: false, - mileage10: false, - rating5: false, - rating4: false, - rating3: false, - rating2: false, - rating1: false - }, - showAllCategories: { - type: false, - make: false, - paymentOptions: false, - mileage: false, - rating: false - } - }; - - this.onShowAllToggle = id => { - const showAllCategories = { ...this.state.showAllCategories }; - showAllCategories[id] = !showAllCategories[id]; - this.setState({ showAllCategories }); - }; - - this.onFilterChange = (id, value) => { - const activeFilters = { ...this.state.activeFilters }; - activeFilters[id] = value; - this.setState({ activeFilters }); - }; - - this.getStars = count => { - const stars = []; - - for (let i = 0; i < count; i++) { - stars.push(); - } - - return ( - - {`${count} stars`} - {stars} - - ); - }; - } - - render() { - const { activeFilters, showAllCategories } = this.state; - const maxShowCount = 5; - const leeway = 2; - return ( -
- - - - - this.onShowAllToggle('type')} - > - this.onFilterChange('typeSUV', e.target.checked)} - > - SUV - - this.onFilterChange('typeSedan', e.target.checked)} - > - Sedan - - this.onFilterChange('typePickup', e.target.checked)} - > - Pickup Truck - - this.onFilterChange('typeSports', e.target.checked)} - > - Sports Car - - - this.onShowAllToggle('manufacturer')} - > - this.onFilterChange('makeChevy', e.target.checked)} - > - Chevrolet - - this.onFilterChange('makeFord', e.target.checked)} - > - Ford - - this.onFilterChange('makeDodge', e.target.checked)} - > - Dodge - - this.onFilterChange('makeVolkswagen', e.target.checked)} - > - Volkswagen - - this.onFilterChange('makeHyundai', e.target.checked)} - > - Hyundai - - this.onFilterChange('makeHonda', e.target.checked)} - > - Honda - - this.onFilterChange('makeToyota', e.target.checked)} - > - Toyota - - this.onFilterChange('makeMercedes', e.target.checked)} - > - Mercedes - - this.onFilterChange('makeBMW', e.target.checked)} - > - BMW - - this.onFilterChange('makeInfiniti', e.target.checked)} - > - Infiniti - - this.onFilterChange('makeLexus', e.target.checked)} - > - Lexus - - this.onFilterChange('makeAcura', e.target.checked)} - > - Acura - - - this.onShowAllToggle('payment')} - > - } - checked={activeFilters.paymentPaypal} - onClick={e => this.onFilterChange('paymentPaypal', e.target.checked)} - > - PayPal - - } - checked={activeFilters.paymentDiscover} - onClick={e => this.onFilterChange('paymentDiscover', e.target.checked)} - > - Discover - - } - checked={activeFilters.paymentVisa} - onClick={e => this.onFilterChange('paymentVisa', e.target.checked)} - > - Visa - - } - checked={activeFilters.paymentMastercard} - onClick={e => this.onFilterChange('paymentMastercard', e.target.checked)} - > - Mastercard - - } - checked={activeFilters.paymentAmex} - onClick={e => this.onFilterChange('paymentAmex', e.target.checked)} - > - American Express - - } - checked={activeFilters.paymentDinersClub} - onClick={e => this.onFilterChange('paymentDinersClub', e.target.checked)} - > - {"Diner's Club"} - - - this.onShowAllToggle('mileage')} - > - this.onFilterChange('mileage50', e.target.checked)} - > - 50+ - - this.onFilterChange('mileage40', e.target.checked)} - > - 40-50 - - this.onFilterChange('mileage30', e.target.checked)} - > - 30-40 - - this.onFilterChange('mileage20', e.target.checked)} - > - 20-30 - - this.onFilterChange('mileage10', e.target.checked)} - > - {'< 20'} - - - this.onShowAllToggle('rating')} - > - this.onFilterChange('rating5', e.target.checked)} - /> - this.onFilterChange('rating4', e.target.checked)} - /> - this.onFilterChange('rating3', e.target.checked)} - /> - this.onFilterChange('rating2', e.target.checked)} - /> - this.onFilterChange('rating1', e.target.checked)} - /> - - -
- ); - } -} -``` diff --git a/packages/react-catalog-view-extension/src/components/FilterSidePanel/examples/filterSidePanel.css b/packages/react-catalog-view-extension/src/components/FilterSidePanel/examples/filterSidePanel.css deleted file mode 100644 index bf5143d2d59..00000000000 --- a/packages/react-catalog-view-extension/src/components/FilterSidePanel/examples/filterSidePanel.css +++ /dev/null @@ -1,50 +0,0 @@ -.filter-panel-pf { - margin: 0 0 30px; - padding: 0 15px; -} - -.filter-panel-pf-category { - margin-top: 20px; -} - -.filter-panel-pf-category:first-of-type { - margin-top: 0; -} - -.filter-panel-pf-category-title { - border: 0; - font-size: inherit; - margin: 0; - font-weight: 700; -} - -.filter-panel-pf-category-items { - margin-top: 0; - margin-bottom: 0; -} - -.filter-panel-pf-category-items .pf-c-button.pf-m-link { - padding: 0; -} - -.filter-panel-pf-category-item { - font-weight: 400; - margin-bottom: 0; - margin-top: 5px; -} - -.filter-panel-pf-category-item:first-of-type { - margin-top: 0; -} - -.filter-panel-pf-category-item .pf-c-check__input { - margin-left: 0px; -} - -.filter-panel-pf-category-item .item-icon { - padding-right: 3px; -} - -.filter-panel-pf-category-item .item-count { - padding-left: 3px; -} diff --git a/packages/react-catalog-view-extension/src/components/FilterSidePanel/index.ts b/packages/react-catalog-view-extension/src/components/FilterSidePanel/index.ts deleted file mode 100644 index 63f2a680ed9..00000000000 --- a/packages/react-catalog-view-extension/src/components/FilterSidePanel/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './FilterSidePanelCategoryItem'; -export * from './FilterSidePanel'; -export * from './FilterSidePanelCategory'; diff --git a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertiesSidePanel.test.tsx b/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertiesSidePanel.test.tsx deleted file mode 100644 index d937e16022b..00000000000 --- a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertiesSidePanel.test.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; -import OkIcon from '@patternfly/react-icons/dist/esm/icons/ok-icon'; -import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; -import GlobeIcon from '@patternfly/react-icons/dist/esm/icons/globe-icon'; - -import { PropertiesSidePanel, PropertyItem } from './'; - -test('PropertyItem renders properly', () => { - const component = mount( - - ); - expect(component.render()).toMatchSnapshot(); -}); - -test('PropertiesSidePanel renders properly', () => { - const component = mount( - - - - Certified - - } - /> - - - - https://quay.io/repository/redhat/prometheus-operator - - } - /> - - 0.22.2 - - } - /> - - Aug 23, 1:58pm - - } - /> - Red Hat} /> - - ); - expect(component.render()).toMatchSnapshot(); -}); diff --git a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertiesSidePanel.tsx b/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertiesSidePanel.tsx deleted file mode 100644 index ce20d4083e8..00000000000 --- a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertiesSidePanel.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -export interface PropertySidePanelProps extends React.HTMLProps { - /** Additional css classes for the Property Item */ - className?: string; - /** Children, should be PropertyItem items plus any action buttons, etc. */ - children?: React.ReactNode; -} - -export const PropertiesSidePanel: React.FunctionComponent = ({ - className = '', - children = null, - ...props -}: PropertySidePanelProps) => { - const classes = css('properties-side-panel-pf', className); - - return ( -
- {children} -
- ); -}; -PropertiesSidePanel.displayName = 'PropertiesSidePanel'; diff --git a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertyItem.tsx b/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertyItem.tsx deleted file mode 100644 index 18cc8480b65..00000000000 --- a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/PropertyItem.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -import { Text, TextVariants } from '@patternfly/react-core'; - -export interface PropertyItemProps extends Omit, 'label' | 'value'> { - /** Additional css classes for the Property Item */ - className?: string; - /** Label for the property */ - label: string | React.ReactNode; - /** Value of the property */ - value: string | React.ReactNode; -} - -export const PropertyItem: React.FunctionComponent = ({ - className = '', - label, - value = null, - ...props -}: PropertyItemProps) => { - const classes = css('properties-side-panel-pf-property', className); - return ( -
- - {label} - -
{value}
-
- ); -}; -PropertyItem.displayName = 'PropertyItem'; diff --git a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/__snapshots__/PropertiesSidePanel.test.tsx.snap b/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/__snapshots__/PropertiesSidePanel.test.tsx.snap deleted file mode 100644 index e59dde946a1..00000000000 --- a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/__snapshots__/PropertiesSidePanel.test.tsx.snap +++ /dev/null @@ -1,228 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`PropertiesSidePanel renders properly 1`] = ` -
-
-
- Operator Version -
-
- 0.9.8 (latest) -
-
-
-
- Certified Level -
-
- - - Certified - -
-
-
-
- Provider -
-
- Red Hat, Inc -
-
-
-
- Health Index -
-
- A -
-
- -
-
- Container Image -
- -
-
-
- Created At -
-
- - - Aug 23, 1:58pm - -
-
-
-
- Support -
- -
-
-`; - -exports[`PropertyItem renders properly 1`] = ` -
-
- Operator Version -
-
- 0.9.8 (latest) -
-
-`; diff --git a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/examples/PropertiesSidePanel.md b/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/examples/PropertiesSidePanel.md deleted file mode 100644 index d51494541c2..00000000000 --- a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/examples/PropertiesSidePanel.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: Catalog view properties side panel -section: extensions -propComponents: ['PropertiesSidePanel', 'PropertyItem'] ---- - -import { PropertiesSidePanel, PropertyItem } from '@patternfly/react-catalog-view-extension'; -import OkIcon from '@patternfly/react-icons/dist/esm/icons/ok-icon'; -import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; -import GlobeIcon from '@patternfly/react-icons/dist/esm/icons/globe-icon'; -import './propertiesSidePanel.css'; - -## Introduction -Note: PropertiesSidePanel lives in its own package at [`@patternfly/react-catalog-view-extension`](https://www.npmjs.com/package/@patternfly/react-catalog-view-extension)! - -This package is currently an extension. Extension components do not undergo the same rigorous design or coding review process as core PatternFly components. If enough members of the community find them useful, we will work to move them into our core PatternFly system by starting the design process for the idea. - - -## Examples - -### Properties side panel with property items -```js -import React from 'react'; -import { PropertiesSidePanel, PropertyItem } from '@patternfly/react-catalog-view-extension'; -import OkIcon from '@patternfly/react-icons/dist/esm/icons/ok-icon'; -import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; -import GlobeIcon from '@patternfly/react-icons/dist/esm/icons/globe-icon'; - -
- - - - Certified - - } - /> - - - - https://quay.io/repository/redhat/prometheus-operator - - } - /> - - 0.22.2 - - } - /> - - Aug 23, 1:58pm - - } - /> - Red Hat} /> - -
-``` diff --git a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/examples/propertiesSidePanel.css b/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/examples/propertiesSidePanel.css deleted file mode 100644 index 8735ccf7644..00000000000 --- a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/examples/propertiesSidePanel.css +++ /dev/null @@ -1,21 +0,0 @@ -.properties-side-panel-pf { - width: 165px; -} - -.properties-side-panel-pf-property { - margin-top: 24px; } -.properties-side-panel-pf-property:first-of-type { - margin-top: 0; -} - -.properties-side-panel-pf-property-label { - font-weight: 700 !important; - font-size: 14px !important; - margin: 0 !important; -} - -.properties-side-panel-pf-property-value { - font-size: 14px !important; - margin-top: 8px; - word-break: break-word; -} diff --git a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/index.ts b/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/index.ts deleted file mode 100644 index 858143a4522..00000000000 --- a/packages/react-catalog-view-extension/src/components/PropertiesSidePanel/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './PropertiesSidePanel'; -export * from './PropertyItem'; diff --git a/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabs.test.tsx b/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabs.test.tsx deleted file mode 100644 index 9f0e684e5f7..00000000000 --- a/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabs.test.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; - -import { VerticalTabs } from './VerticalTabs'; -import { VerticalTabsTab } from './VerticalTabsTab'; - -test('Vertical Tabs renders tabs properly', () => { - const component = mount( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); - expect(component).toMatchSnapshot(); -}); - -test('Vertical Tabs renders restricted tabs properly', () => { - const component = mount( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); - expect(component).toMatchSnapshot(); -}); - -test('Vertical Tabs Tab onActivate is called correctly', () => { - const onActivateMock = jest.fn(); - - const component = mount(); - component.find('#text-click > a').simulate('click'); - - expect(component).toMatchSnapshot(); - expect(onActivateMock).toBeCalled(); -}); - -test('Vertical Tabs Tab wrap styling is set correctly', () => { - const component = mount( -
- - - - -
- ); - - expect(component).toMatchSnapshot(); -}); diff --git a/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabs.tsx b/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabs.tsx deleted file mode 100644 index 92340f16cf1..00000000000 --- a/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabs.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -export interface VerticalTabsProps extends React.HTMLProps { - /** Children nodes */ - children?: React.ReactNode; - /** Additional css classes */ - className?: string; - /** Flag to restrict shown tabs to active tabs, their parents, their siblings, and direct children */ - restrictTabs?: boolean; - /** Flag if a direct child is active (only used in restrictTabs mode) */ - activeTab?: boolean; -} - -export const VerticalTabs: React.FunctionComponent = ({ - children = null, - className = '', - restrictTabs = false, - activeTab = false, - ...props -}: VerticalTabsProps) => { - const classes = css('vertical-tabs-pf', { 'restrict-tabs': restrictTabs, 'active-tab': activeTab }, className); - return ( -
    - {children} -
- ); -}; -VerticalTabs.displayName = 'VerticalTabs'; diff --git a/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabsTab.tsx b/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabsTab.tsx deleted file mode 100644 index 37e9ee798d7..00000000000 --- a/packages/react-catalog-view-extension/src/components/VerticalTabs/VerticalTabsTab.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -export interface VerticalTabsTabProps extends Omit, 'title'> { - /** Child tab nodes (VerticalTabsTab's) */ - children?: React.ReactNode; - /** Additional css classes */ - className?: string; - /** Title for the tab */ - title?: string | React.ReactNode; - /** Title wrap style */ - wrapStyle?: 'wrap' | 'truncate' | 'nowrap'; - /** Flag if this is the active tab */ - active?: boolean; - /** Flag if a descendant tab is active (used only in restrictTabs mode) */ - hasActiveDescendant?: boolean; - /** Flag to force show the tab (if parent tab is shown, used only in restrictTabs mode) */ - shown?: boolean; - /** Callback function when the tab is activated */ - onActivate?: () => void; - /** HREF location */ - href?: string; -} - -export const VerticalTabsTab: React.FunctionComponent = ({ - children = null, - className = '', - title = null, - wrapStyle = 'wrap', - active = false, - hasActiveDescendant = false, - shown = false, - onActivate = null, - href, - ...props -}: VerticalTabsTabProps) => { - const classes = css('vertical-tabs-pf-tab', { active, 'active-descendant': hasActiveDescendant, shown }, className); - - const linkClasses = css({ - 'no-wrap': wrapStyle === 'nowrap', - truncate: wrapStyle === 'truncate' - }); - - const handleActivate = (e: React.SyntheticEvent) => { - e.preventDefault(); - if (onActivate) { - onActivate(); - } - }; - - return ( -
  • - handleActivate(e)} href={href}> - {title} - - {children} -
  • - ); -}; -VerticalTabsTab.displayName = 'VerticalTabsTab'; diff --git a/packages/react-catalog-view-extension/src/components/VerticalTabs/__snapshots__/VerticalTabs.test.tsx.snap b/packages/react-catalog-view-extension/src/components/VerticalTabs/__snapshots__/VerticalTabs.test.tsx.snap deleted file mode 100644 index 2940c4f192c..00000000000 --- a/packages/react-catalog-view-extension/src/components/VerticalTabs/__snapshots__/VerticalTabs.test.tsx.snap +++ /dev/null @@ -1,834 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Vertical Tabs Tab onActivate is called correctly 1`] = ` - -
  • - - Click Me - -
  • -
    -`; - -exports[`Vertical Tabs Tab wrap styling is set correctly 1`] = ` - -`; - -exports[`Vertical Tabs renders restricted tabs properly 1`] = ` - - - -`; - -exports[`Vertical Tabs renders tabs properly 1`] = ` - - - -`; diff --git a/packages/react-catalog-view-extension/src/components/VerticalTabs/examples/VerticalTabs.md b/packages/react-catalog-view-extension/src/components/VerticalTabs/examples/VerticalTabs.md deleted file mode 100644 index 9415b5ffdf9..00000000000 --- a/packages/react-catalog-view-extension/src/components/VerticalTabs/examples/VerticalTabs.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -id: Catalog view vertical tabs -section: extensions -propComponents: ['VerticalTabs', 'VerticalTabsTab'] ---- - -import { VerticalTabs, VerticalTabsTab } from '@patternfly/react-catalog-view-extension'; -import './verticalTab.css'; - -## Introduction -Note: Vertical tabs lives in its own package at [`@patternfly/react-catalog-view-extension`](https://www.npmjs.com/package/@patternfly/react-catalog-view-extension)! - -This package is currently an extension. Extension components do not undergo the same rigorous design or coding review process as core PatternFly components. If enough members of the community find them useful, we will work to move them into our core PatternFly system by starting the design process for the idea. - -## Examples -### Basic -```js -import React from 'react'; -import { VerticalTabs, VerticalTabsTab } from '@patternfly/react-catalog-view-extension'; - -class MockVerticalTabsExample extends React.Component { - constructor(props) { - super(props); - this.state = { activeTabId: 'all' }; - this.onActivateTab = id => { - this.setState({ activeTabId: id }); - }; - } - - render() { - const { restrictTabs, wrapStyle } = this.props; - const { activeTabId } = this.state; - - const topLevelIds = ['all', 'one', 'two', 'three', 'four', 'five', 'six', 'seven']; - - const renderTab = (id, title, children, props) => { - const childIds = React.Children.map(children, child => child.props.id); - - return ( - this.onActivateTab(id)} - active={activeTabId === id} - hasActiveDescendant={activeTabId.startsWith(id)} - {...props} - > - {children && ( - - {children} - - )} - - ); - }; - - return ( - - {renderTab('all', 'All', null, { shown: true })} - {renderTab('one', 'Tab One', [ - renderTab('one-one', 'Tab One-One', [ - renderTab('one-one-one', 'About Modal', null, {href: "../components/about-modal"}), - renderTab('one-one-two', 'Accordion', null, {href: "../components/accordion"}), - renderTab('one-one-three', 'Redhat', null, {href: "http://www.redhat.com"}) - ]), - renderTab('one-two', 'Tab One-Two', [ - renderTab('one-two-one', 'Tab One-Two-One'), - renderTab('one-two-two', 'Tab One-Two-Two'), - renderTab('one-two-three', 'Tab One-Two-Three') - ]), - renderTab('one-three', 'Tab One-Thee') - ])} - {renderTab('two', 'Tab Two', [ - renderTab('two-one', 'Tab Two-One'), - renderTab('two-two', 'Tab Two-Two'), - renderTab('two-three', 'Tab Two-Three') - ])} - {renderTab('three', 'Tab Three - Donec id elit non mi porta gravida at eget metus')} - {renderTab('four', 'Tab Four')} - {renderTab('five', 'Tab Five')} - {renderTab('six', 'Tab Six')} - {renderTab('seven', 'Tab Seven')} - - ); - } -} -``` diff --git a/packages/react-catalog-view-extension/src/components/VerticalTabs/examples/verticalTab.css b/packages/react-catalog-view-extension/src/components/VerticalTabs/examples/verticalTab.css deleted file mode 100644 index 80de1a9db03..00000000000 --- a/packages/react-catalog-view-extension/src/components/VerticalTabs/examples/verticalTab.css +++ /dev/null @@ -1,64 +0,0 @@ -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf { - list-style: none; - margin: 0 0 30px; - padding: 0; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf .vertical-tabs-pf { - margin-bottom: 0; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab { - margin-top: 4px; - position: relative; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab > a { - color: initial; - display: inline-block; - font-size: 13px; - padding: 3px 6px 3px 15px; - vertical-align: top; - width: 100%; - word-break: break-word; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab > a:hover, .ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab > a:focus { - color: #0088ce; - text-decoration: none; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab > a.no-wrap { - overflow-x: hidden; - white-space: nowrap; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab > a.truncate { - overflow-x: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab.active > a { - color: #0088ce; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab.active > a::before { - background: #0088ce; - content: " "; - left: 0; - position: absolute; - width: 3px; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab:first-of-type { - margin-top: 0; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf-tab > .vertical-tabs-pf > .vertical-tabs-pf-tab { - position: initial; - padding-left: 15px; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf.restrict-tabs .vertical-tabs-pf-tab { - display: none; - /* Show any active tab, tab that has an active descendant, or is force shown */ -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf.restrict-tabs .vertical-tabs-pf-tab.active, .ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf.restrict-tabs .vertical-tabs-pf-tab.active-descendant, .ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf.restrict-tabs .vertical-tabs-pf-tab.shown { - display: block; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf.restrict-tabs.active-tab > .vertical-tabs-pf-tab { - display: block; -} -.ws-react-e-catalog-view-vertical-tabs .vertical-tabs-pf.restrict-tabs .vertical-tabs-pf-tab.active > .vertical-tabs-pf > .vertical-tabs-pf-tab { - display: block; -} diff --git a/packages/react-catalog-view-extension/src/components/VerticalTabs/index.ts b/packages/react-catalog-view-extension/src/components/VerticalTabs/index.ts deleted file mode 100644 index 7e9234d46ac..00000000000 --- a/packages/react-catalog-view-extension/src/components/VerticalTabs/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './VerticalTabs'; -export * from './VerticalTabsTab'; diff --git a/packages/react-catalog-view-extension/src/components/index.ts b/packages/react-catalog-view-extension/src/components/index.ts deleted file mode 100644 index 903b94b134a..00000000000 --- a/packages/react-catalog-view-extension/src/components/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** Keep alphabetically sorted */ -export * from './CatalogItemHeader'; -export * from './CatalogTile'; -export * from './VerticalTabs'; -export * from './PropertiesSidePanel'; -export * from './FilterSidePanel'; diff --git a/packages/react-catalog-view-extension/src/helpers/util.test.js b/packages/react-catalog-view-extension/src/helpers/util.test.js deleted file mode 100644 index ba0a632e76a..00000000000 --- a/packages/react-catalog-view-extension/src/helpers/util.test.js +++ /dev/null @@ -1,5 +0,0 @@ -import { getUniqueId } from './util'; - -test('getUniqueId', () => { - expect(getUniqueId()).not.toBe(getUniqueId()); -}); diff --git a/packages/react-catalog-view-extension/src/helpers/util.ts b/packages/react-catalog-view-extension/src/helpers/util.ts deleted file mode 100644 index eef2827bbad..00000000000 --- a/packages/react-catalog-view-extension/src/helpers/util.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; - -/** - * @param {string} prefix - String to prefix unique ID with - */ -export function getUniqueId(prefix = 'pf') { - const uid = - new Date().getTime() + - Math.random() - .toString(36) - .slice(2); - return `${prefix}-${uid}`; -} - -/** - * Returns the given React children prop as a regular array of React nodes. - * - * @param {React.ReactNode} children - Child react node - */ -export const childrenToArray = (children: React.ReactNode) => - children && React.Children.count(children) > 0 && React.Children.toArray(children); diff --git a/packages/react-catalog-view-extension/tsconfig.json b/packages/react-catalog-view-extension/tsconfig.json deleted file mode 100644 index 80c91eb0ee2..00000000000 --- a/packages/react-catalog-view-extension/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "compilerOptions": { - "rootDir": "./src", - "outDir": "./dist/esm", - "tsBuildInfoFile": "dist/esm.tsbuildinfo" - }, - "include": [ - "./src/*", - "./src/**/*" - ], - "references": [ - { - "path": "../react-core" - }, - { - "path": "../react-styles" - }, - { - "path": "../react-table" - } - ] -} diff --git a/packages/react-charts/.gitignore b/packages/react-charts/.gitignore new file mode 100644 index 00000000000..3e0402f878e --- /dev/null +++ b/packages/react-charts/.gitignore @@ -0,0 +1,4 @@ +/deprecated +/echarts +/next +/victory diff --git a/packages/react-charts/CHANGELOG.md b/packages/react-charts/CHANGELOG.md index 5fb2050cb50..6880ff56aa0 100644 --- a/packages/react-charts/CHANGELOG.md +++ b/packages/react-charts/CHANGELOG.md @@ -3,4504 +3,1202 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. -# 6.41.0 (2022-01-14) - - -### Features - -* **DescriptionList:** add option to fill columns first ([#6736](https://github.com/patternfly/patternfly-react/issues/6736)) ([c955c29](https://github.com/patternfly/patternfly-react/commit/c955c2917dbc4b85ce58fac4f93845c429186e1b)) - - - - - -## 6.40.2 (2022-01-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.40.1 (2022-01-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.40.0 (2022-01-12) - - -### Features - -* **expandable-section:** added indented variation ([#6763](https://github.com/patternfly/patternfly-react/issues/6763)) ([703b922](https://github.com/patternfly/patternfly-react/commit/703b9224e43bedd5b37ec41d8f26f2939836d610)) - - - - - -## 6.39.1 (2022-01-11) - - -### Bug Fixes - -* **Select:** update typeahead Select children when any option attribute changes ([#6747](https://github.com/patternfly/patternfly-react/issues/6747)) ([1e03f3c](https://github.com/patternfly/patternfly-react/commit/1e03f3c6d0a7c507e33398c98863e40bb2233a62)) - - - - - -# 6.39.0 (2022-01-11) - - -### Features - -* **ToggleGroup:** support disabling all items under the parent ([#6700](https://github.com/patternfly/patternfly-react/issues/6700)) ([a60c8f3](https://github.com/patternfly/patternfly-react/commit/a60c8f3485546c797750451714a70b7e84a4ba0f)) - - - - - -## 6.38.1 (2022-01-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.38.0 (2022-01-11) - - -### Features - -* **Table:** update clickable area for checks/radios ([#6754](https://github.com/patternfly/patternfly-react/issues/6754)) ([c4f3c2d](https://github.com/patternfly/patternfly-react/commit/c4f3c2d7f515e3d6ad73d8b52238ca426281469a)) - - - - - -## 6.37.2 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.37.1 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.37.0 (2022-01-10) - - -### Features - -* **Dropdown:** add plain-text variant support ([#6721](https://github.com/patternfly/patternfly-react/issues/6721)) ([e5000e3](https://github.com/patternfly/patternfly-react/commit/e5000e36194e36b9c6ae49efdb0a513125efcb70)) - - - - - -## 6.36.11 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.36.10 (2022-01-10) - - -### Bug Fixes - -* **Tabs:** allow href navigation from tabs ([#6755](https://github.com/patternfly/patternfly-react/issues/6755)) ([290d89a](https://github.com/patternfly/patternfly-react/commit/290d89aed2dd4517db9859cc80ef2745cb8a779b)) - - - - - -## 6.36.9 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.36.8 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.36.7 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.36.6 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.36.5 (2022-01-07) - - -### Bug Fixes - -* **jumplinks:** Updated JumpLinks demo to allow for horizontal display ([#6731](https://github.com/patternfly/patternfly-react/issues/6731)) ([f37b934](https://github.com/patternfly/patternfly-react/commit/f37b9342e678da247056c73767d5d40ff5435bda)) - - - - - -## 6.36.4 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.36.3 (2022-01-06) - - -### Bug Fixes - -* **TopologyControlBar:** Update screen reader className to latest ([#6739](https://github.com/patternfly/patternfly-react/issues/6739)) ([ed9da57](https://github.com/patternfly/patternfly-react/commit/ed9da575fddf9fe7af8a891972f7a66520785411)) - - - - - -## 6.36.2 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.36.1 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.36.0 (2022-01-05) - - -### Features - -* **Table:** allow a generic to be passed for cell props ([#6691](https://github.com/patternfly/patternfly-react/issues/6691)) ([e22c7be](https://github.com/patternfly/patternfly-react/commit/e22c7bebf630b7cd71e4dc434c593b69fa2fb2c8)) - - - - - -## 6.35.3 (2022-01-04) - - -### Bug Fixes - -* **docs:** fix broken theme-patternfly-org link ([#6726](https://github.com/patternfly/patternfly-react/issues/6726)) ([4ba15e9](https://github.com/patternfly/patternfly-react/commit/4ba15e9d9611afbb80d995e4d63f5478c4212a9e)) - - - - - -## 6.35.2 (2022-01-04) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.35.1 (2022-01-04) - - -### Bug Fixes - -* **OverflowMenu:** pass HTMLDivElements props to group and control divs ([#6674](https://github.com/patternfly/patternfly-react/issues/6674)) ([e6d0d64](https://github.com/patternfly/patternfly-react/commit/e6d0d6406a07de04f4b232ca9a21247c0e9746c0)) - - - - - -# 6.35.0 (2021-12-22) - - -### Features - -* **Toolbar:** support customizing text in ToolbarChipGroupContent ([#6694](https://github.com/patternfly/patternfly-react/issues/6694)) ([24266ad](https://github.com/patternfly/patternfly-react/commit/24266adf569c027574abd1503b5e46974220349a)) - - - - - -## 6.34.5 (2021-12-16) - - -### Bug Fixes - -* **LogViewer:** fix the issue that scrollbar could compress the content of the logs ([#6702](https://github.com/patternfly/patternfly-react/issues/6702)) ([11aab1f](https://github.com/patternfly/patternfly-react/commit/11aab1f71a1aa9959cf14b887ab55b845a794a00)) - - - - - -## 6.34.4 (2021-12-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.34.3 (2021-12-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.34.2 (2021-12-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.34.1 (2021-12-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.34.0 (2021-12-09) - - -### Features - -* **Popover:** add composable header and alert variants ([#6664](https://github.com/patternfly/patternfly-react/issues/6664)) ([9028e8b](https://github.com/patternfly/patternfly-react/commit/9028e8ba5d674bde6a7e29532f7926e200dd632a)) - - - - - -## 6.33.1 (2021-12-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.33.0 (2021-12-08) - - -### Features - -* **DualListSelector:** add composable tree example ([#6652](https://github.com/patternfly/patternfly-react/issues/6652)) ([5fe977b](https://github.com/patternfly/patternfly-react/commit/5fe977becb5dea615724abf846f315e50931c188)) - - - - - -## 6.32.1 (2021-12-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.32.0 (2021-12-06) - - -### Features - -* **Card:** Add disabled card and clean up props ([#6659](https://github.com/patternfly/patternfly-react/issues/6659)) ([86f225a](https://github.com/patternfly/patternfly-react/commit/86f225ab2e02d617e2d380c4a7f7593037c50e84)) - - - - - -# 6.31.0 (2021-12-06) - - -### Features - -* **MenuToggle:** add plain with text variant ([#6627](https://github.com/patternfly/patternfly-react/issues/6627)) ([1f4ca5e](https://github.com/patternfly/patternfly-react/commit/1f4ca5e36d7077da3ff3e6918874048c784216e0)) - - - - - -# 6.30.0 (2021-12-06) - - -### Features - -* **Dropdown:** add toggle variants ([#6651](https://github.com/patternfly/patternfly-react/issues/6651)) ([6414309](https://github.com/patternfly/patternfly-react/commit/64143094aec86aed86adb320e059d987af4f5f24)) - - - - - -## 6.29.1 (2021-12-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.29.0 (2021-12-03) - - -### Features - -* **Select:** add ability to persist filtered children state ([#6670](https://github.com/patternfly/patternfly-react/issues/6670)) ([f618577](https://github.com/patternfly/patternfly-react/commit/f618577582e389409978bd1d6512ca0cf5d855cf)) - - - - - -## 6.28.17 (2021-12-03) - - -### Bug Fixes - -* **Slider:** fixed examples with custom steps and input ([#6662](https://github.com/patternfly/patternfly-react/issues/6662)) ([b4cab38](https://github.com/patternfly/patternfly-react/commit/b4cab38a2492564bf91e3711ce322951bcc6a051)) - - - - - -## 6.28.16 (2021-12-02) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.15 (2021-12-02) - - -### Bug Fixes - -* **Tile:** fix selecting tile in tile demo ([#6653](https://github.com/patternfly/patternfly-react/issues/6653)) ([e12e44d](https://github.com/patternfly/patternfly-react/commit/e12e44d4b623de305b7df04174144a9496d282a7)) - - - - - -## 6.28.14 (2021-12-01) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.13 (2021-11-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.12 (2021-11-30) - - -### Bug Fixes - -* **action-list:** added support for classname ([#6647](https://github.com/patternfly/patternfly-react/issues/6647)) ([dd3d2ce](https://github.com/patternfly/patternfly-react/commit/dd3d2ce32b4d3e7562faf465abdc508e17f097d9)) - - - - - -## 6.28.11 (2021-11-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.10 (2021-11-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.9 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.8 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.7 (2021-11-18) - - -### Bug Fixes - -* **pagination:** updated toggleTemplate prop description to include ofWord prop ([#6622](https://github.com/patternfly/patternfly-react/issues/6622)) ([26733a6](https://github.com/patternfly/patternfly-react/commit/26733a6a256ad0e873afbc268a712027470fdeaa)) - - - - - -## 6.28.6 (2021-11-18) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.5 (2021-11-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.4 (2021-11-15) - - -### Bug Fixes - -* **FileUpload:** Downgrade react-dropzone back to 9.0.0 to avoid a breaking type change, fix behavior regressions ([#6610](https://github.com/patternfly/patternfly-react/issues/6610)) ([574bf4f](https://github.com/patternfly/patternfly-react/commit/574bf4ff3ccf7f67ce750bc48067eaf826e99990)) - - - - - -## 6.28.3 (2021-11-15) - - -### Bug Fixes - -* **Menu:** allow maxMenuHeight with Scrollabe ([#6608](https://github.com/patternfly/patternfly-react/issues/6608)) ([8c1f12c](https://github.com/patternfly/patternfly-react/commit/8c1f12c2b0e86bbc5ba1071db3ebf29fee7421a0)) - - - - - -## 6.28.2 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.28.1 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.28.0 (2021-11-12) - - -### Features - -* **card:** added hoverable/selectable/selected-raised variant ([#6565](https://github.com/patternfly/patternfly-react/issues/6565)) ([8c60568](https://github.com/patternfly/patternfly-react/commit/8c60568ba4fa18398fed636710e222ce506de82c)) - - - - - -## 6.27.2 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.27.1 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.27.0 (2021-11-11) - - -### Features - -* **ComposableTable:** add sticky columns and nested headers ([#6538](https://github.com/patternfly/patternfly-react/issues/6538)) ([f11245b](https://github.com/patternfly/patternfly-react/commit/f11245bfccc8c6c02a9d5545a69ed533743cc552)) - - - - - -# 6.26.0 (2021-11-11) - - -### Features - -* **contextselector:** added support for context selector items as links ([#6554](https://github.com/patternfly/patternfly-react/issues/6554)) ([c465388](https://github.com/patternfly/patternfly-react/commit/c4653881eee0cd8ec8e3a7125bbef0bded9f2de0)) - - - - - -# 6.25.0 (2021-11-11) - - -### Features - -* **Navigation:** Added exemple with third level ([#6564](https://github.com/patternfly/patternfly-react/issues/6564)) ([c30da53](https://github.com/patternfly/patternfly-react/commit/c30da532855118f705c8cfc87c545bb1eea11ebb)) - - - - - -# 6.24.0 (2021-11-11) - - -### Features - -* enhance type correctness of CodeEditor ([#6579](https://github.com/patternfly/patternfly-react/issues/6579)) ([e1ad65c](https://github.com/patternfly/patternfly-react/commit/e1ad65c225968d5a9c74019d19e4a3c5e2666926)) - - - - - -## 6.23.4 (2021-11-10) - - -### Bug Fixes - -* **jumplinks:** fixed to always set clicked item as active ([#6542](https://github.com/patternfly/patternfly-react/issues/6542)) ([845c98f](https://github.com/patternfly/patternfly-react/commit/845c98f5f3df8aa9b6acc190707c5f1d7bf3ca38)) - - - - - -## 6.23.3 (2021-11-10) - - -### Bug Fixes - -* **Menu:** stop passing disableHover to DrilldownMenu DOM ([#6571](https://github.com/patternfly/patternfly-react/issues/6571)) ([63dcf25](https://github.com/patternfly/patternfly-react/commit/63dcf256723848ff3789828fc0a5f86d5009fc87)) - - - - - -## 6.23.2 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.23.1 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.23.0 (2021-11-09) - - -### Features - -* **Table:** set default sort direction ([#6544](https://github.com/patternfly/patternfly-react/issues/6544)) ([9ee4942](https://github.com/patternfly/patternfly-react/commit/9ee49428c8e1041721f2a09f8176a5aba3335049)) - - - - - -## 6.22.4 (2021-11-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.22.3 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.22.2 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.22.1 (2021-11-08) - - -### Bug Fixes - -* **acccessconsoles:** use object type Select options values in order to not mix displayed text with option keys ([#6496](https://github.com/patternfly/patternfly-react/issues/6496)) ([975c8e1](https://github.com/patternfly/patternfly-react/commit/975c8e14d7ea8c53eb4048ea6ef73e804b3ad2be)) - - - - - -# 6.22.0 (2021-11-04) - - -### Features - -* **log-viewer:** support ANSI color ([#6519](https://github.com/patternfly/patternfly-react/issues/6519)) ([936a699](https://github.com/patternfly/patternfly-react/commit/936a699b0514a492d3c40be08932fb7bab275cce)) - - - - - -## 6.21.11 (2021-11-01) - - -### Bug Fixes - -* **AboutModal:** allow to disable FocusTrap ([#6509](https://github.com/patternfly/patternfly-react/issues/6509)) ([72536e1](https://github.com/patternfly/patternfly-react/commit/72536e1f73641ff3f19f865f08dbb41ad0ee7b9f)) - - - - - -## 6.21.10 (2021-10-29) - - -### Bug Fixes - -* **Banner:** forward props ([#6511](https://github.com/patternfly/patternfly-react/issues/6511)) ([e36c890](https://github.com/patternfly/patternfly-react/commit/e36c89077afa82340994c0e3c0fc929e601e01bc)) - - - - - -## 6.21.9 (2021-10-28) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.21.8 (2021-10-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.21.7 (2021-10-27) - - -### Bug Fixes - -* change transformer cjs package to private ([#6515](https://github.com/patternfly/patternfly-react/issues/6515)) ([efcb357](https://github.com/patternfly/patternfly-react/commit/efcb3573b71541328ce2b16caa80ce33b2a62131)) - - - - - -## 6.21.6 (2021-10-26) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.21.5 (2021-10-26) - - -### Bug Fixes - -* **tokens:** added check for no matching var to avoid infinite loop ([#6502](https://github.com/patternfly/patternfly-react/issues/6502)) ([99605c2](https://github.com/patternfly/patternfly-react/commit/99605c213f12490d0abe75910e05c3e6da26a1f3)) - - - - - -## 6.21.4 (2021-10-26) - - -### Bug Fixes - -* add transformer package ([#6507](https://github.com/patternfly/patternfly-react/issues/6507)) ([daffd28](https://github.com/patternfly/patternfly-react/commit/daffd2864388abe63e625f962a8b38c2b7056209)) - - - - - -## 6.21.3 (2021-10-26) - - -### Bug Fixes - -* **transformer:** publish transformer in patternfly org ([#6506](https://github.com/patternfly/patternfly-react/issues/6506)) ([b739af3](https://github.com/patternfly/patternfly-react/commit/b739af318400b41d4e9a53bdff6232ecc176916e)) - - - - - -## 6.21.2 (2021-10-26) - - -### Bug Fixes - -* **readme:** update react-core readme ([#6505](https://github.com/patternfly/patternfly-react/issues/6505)) ([d4f9a11](https://github.com/patternfly/patternfly-react/commit/d4f9a114584eea7ab67873f199e80b348886e14b)) - - - - - -## 6.21.1 (2021-10-26) - - -### Bug Fixes - -* **DualListSelector:** account for duplicate folders ([#6499](https://github.com/patternfly/patternfly-react/issues/6499)) ([e531e68](https://github.com/patternfly/patternfly-react/commit/e531e68e7adc58459b3630f5c915ed69e3021012)) - - - - - -# 6.21.0 (2021-10-26) - - -### Features - -* **toolbar:** add sticky top modifier to toolbar ([#6447](https://github.com/patternfly/patternfly-react/issues/6447)) ([fe7605a](https://github.com/patternfly/patternfly-react/commit/fe7605a67428b43ec00b3cb2117270296576737c)) - - - - - -## 6.20.1 (2021-10-26) - - -### Bug Fixes - -* **types:** SelectOptionProp made optional ([#6503](https://github.com/patternfly/patternfly-react/issues/6503)) ([716ac80](https://github.com/patternfly/patternfly-react/commit/716ac80e2414507d589ee3002fc0cea0068ae59c)) - - - - - -# 6.20.0 (2021-10-26) - - -### Features - -* **TextInputGroup:** add text input group ([#6482](https://github.com/patternfly/patternfly-react/issues/6482)) ([a02fd4f](https://github.com/patternfly/patternfly-react/commit/a02fd4fe3345245b2252ee5a261f5b1460490642)), closes [patternfly/patternfly-react#6409](https://github.com/patternfly/patternfly-react/issues/6409) - - - - - -## 6.19.4 (2021-10-26) - - -### Bug Fixes - -* **KebabToggle:** adds event to onToggle definition ([#6490](https://github.com/patternfly/patternfly-react/issues/6490)) ([0441575](https://github.com/patternfly/patternfly-react/commit/04415757917062aa13c06b34bd94ef38c2334088)) - - - - - -## 6.19.3 (2021-10-26) - - -### Bug Fixes - -* **Modal:** test clean up ([#6489](https://github.com/patternfly/patternfly-react/issues/6489)) ([c8eaa7c](https://github.com/patternfly/patternfly-react/commit/c8eaa7c838fbedb98ea0f38e4f535488040a72e2)) - - - - - -## 6.19.2 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.19.1 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.19.0 (2021-10-25) - - -### Features - -* **Tabs:** Added support for tab content body with padding, added tabs open and tab secondary tabs demos ([#6484](https://github.com/patternfly/patternfly-react/issues/6484)) ([0ccbe9d](https://github.com/patternfly/patternfly-react/commit/0ccbe9d1e6e0dac0730466c92a90fe2cd9f6560d)) - - - - - -## 6.18.1 (2021-10-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# 6.18.0 (2021-10-21) - - -### Features - -* **label:** added compact label, updated horizontal grid card demo ([#6448](https://github.com/patternfly/patternfly-react/issues/6448)) ([89e0431](https://github.com/patternfly/patternfly-react/commit/89e04317924282140606d45f2292aa3f658b4b6c)) - - - - - -## 6.17.1 (2021-10-21) - - -### Bug Fixes - -* **DescriptionListGroup:** forward props to DOM ([#6466](https://github.com/patternfly/patternfly-react/issues/6466)) ([b78e2aa](https://github.com/patternfly/patternfly-react/commit/b78e2aa9c0360ce8418f6e7b55274ea1a50de518)) - - - - - -# 6.17.0 (2021-10-20) - - -### Features - -* **Progress:** allow node titles ([#6470](https://github.com/patternfly/patternfly-react/issues/6470)) ([46d5252](https://github.com/patternfly/patternfly-react/commit/46d52523ad5111bb11729c2750abe9aeb35d9326)) - - - - - -# 6.16.0 (2021-10-20) - - -### Features - -* **DualListSelector:** add disabled flag ([#6442](https://github.com/patternfly/patternfly-react/issues/6442)) ([85e1314](https://github.com/patternfly/patternfly-react/commit/85e131435be12c2df79336e9fa56987ed3717417)) - - - - - -## 6.15.35 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## 6.15.34 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.32...@patternfly/react-charts@6.15.33) (2021-10-18) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.31...@patternfly/react-charts@6.15.32) (2021-10-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.30...@patternfly/react-charts@6.15.31) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.29...@patternfly/react-charts@6.15.30) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.28...@patternfly/react-charts@6.15.29) (2021-10-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.27...@patternfly/react-charts@6.15.28) (2021-10-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.26...@patternfly/react-charts@6.15.27) (2021-10-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.25...@patternfly/react-charts@6.15.26) (2021-10-01) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.24...@patternfly/react-charts@6.15.25) (2021-09-29) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.23...@patternfly/react-charts@6.15.24) (2021-09-24) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.22...@patternfly/react-charts@6.15.23) (2021-09-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.21...@patternfly/react-charts@6.15.22) (2021-09-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.20...@patternfly/react-charts@6.15.21) (2021-08-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.19...@patternfly/react-charts@6.15.20) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.18...@patternfly/react-charts@6.15.19) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.17...@patternfly/react-charts@6.15.18) (2021-08-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.16...@patternfly/react-charts@6.15.17) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.15...@patternfly/react-charts@6.15.16) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.14...@patternfly/react-charts@6.15.15) (2021-08-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.13...@patternfly/react-charts@6.15.14) (2021-08-02) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.12...@patternfly/react-charts@6.15.13) (2021-07-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.11...@patternfly/react-charts@6.15.12) (2021-07-29) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.10...@patternfly/react-charts@6.15.11) (2021-07-29) - - -### Bug Fixes - -* **charts:** donut chart shows gap ([#6084](https://github.com/patternfly/patternfly-react/issues/6084)) ([cbdfdcd](https://github.com/patternfly/patternfly-react/commit/cbdfdcde74fad13e305a7d6a4272bf02faf32cee)) - - - - - -## [6.15.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.9...@patternfly/react-charts@6.15.10) (2021-07-28) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.8...@patternfly/react-charts@6.15.9) (2021-07-19) - - -### Bug Fixes - -* **charts:** Victory tooltip performance update ([#6049](https://github.com/patternfly/patternfly-react/issues/6049)) ([829d4f4](https://github.com/patternfly/patternfly-react/commit/829d4f4cb441968e9ddfe17b0fed9acf2c3b1428)) - - - - - -## [6.15.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.7...@patternfly/react-charts@6.15.8) (2021-07-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.6...@patternfly/react-charts@6.15.7) (2021-07-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.5...@patternfly/react-charts@6.15.6) (2021-07-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.4...@patternfly/react-charts@6.15.5) (2021-07-01) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.3...@patternfly/react-charts@6.15.4) (2021-06-28) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.2...@patternfly/react-charts@6.15.3) (2021-06-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.1...@patternfly/react-charts@6.15.2) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.15.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.15.0...@patternfly/react-charts@6.15.1) (2021-06-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.15.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.29...@patternfly/react-charts@6.15.0) (2021-06-09) - - -### Features - -* **charts:** Add left and right triangle legend symbols ([#5869](https://github.com/patternfly/patternfly-react/issues/5869)) ([89e45d3](https://github.com/patternfly/patternfly-react/commit/89e45d36c557d6a795ea83f9b63c0733835c0348)) - - - - - -## [6.14.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.28...@patternfly/react-charts@6.14.29) (2021-06-04) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.27...@patternfly/react-charts@6.14.28) (2021-06-02) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.26...@patternfly/react-charts@6.14.27) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.25...@patternfly/react-charts@6.14.26) (2021-05-24) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.24...@patternfly/react-charts@6.14.25) (2021-05-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.23...@patternfly/react-charts@6.14.24) (2021-05-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.22...@patternfly/react-charts@6.14.23) (2021-05-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.21...@patternfly/react-charts@6.14.22) (2021-05-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.20...@patternfly/react-charts@6.14.21) (2021-05-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.19...@patternfly/react-charts@6.14.20) (2021-05-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.18...@patternfly/react-charts@6.14.19) (2021-05-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.17...@patternfly/react-charts@6.14.18) (2021-05-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.16...@patternfly/react-charts@6.14.17) (2021-04-22) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.15...@patternfly/react-charts@6.14.16) (2021-04-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.14...@patternfly/react-charts@6.14.15) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.13...@patternfly/react-charts@6.14.14) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.12...@patternfly/react-charts@6.14.13) (2021-04-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.11...@patternfly/react-charts@6.14.12) (2021-04-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.10...@patternfly/react-charts@6.14.11) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.9...@patternfly/react-charts@6.14.10) (2021-03-25) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.8...@patternfly/react-charts@6.14.9) (2021-03-24) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.7...@patternfly/react-charts@6.14.8) (2021-03-22) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.6...@patternfly/react-charts@6.14.7) (2021-03-16) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.5...@patternfly/react-charts@6.14.6) (2021-03-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.4...@patternfly/react-charts@6.14.5) (2021-03-05) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.3...@patternfly/react-charts@6.14.4) (2021-03-04) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.2...@patternfly/react-charts@6.14.3) (2021-03-04) - - -### Bug Fixes - -* **searchinput:** add searchInputMenuBody class ([#5518](https://github.com/patternfly/patternfly-react/issues/5518)) ([99f0512](https://github.com/patternfly/patternfly-react/commit/99f05123d28a7be887efd1921733fc2dc0bddd6d)) - - - - - -## [6.14.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.1...@patternfly/react-charts@6.14.2) (2021-02-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.14.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.14.0...@patternfly/react-charts@6.14.1) (2021-02-16) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.14.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.14...@patternfly/react-charts@6.14.0) (2021-02-12) - - -### Features - -* **Slider:** Added touch support ([#5453](https://github.com/patternfly/patternfly-react/issues/5453)) ([32ce723](https://github.com/patternfly/patternfly-react/commit/32ce7238d8743f6d4a5f7b128b1293e855d012ca)) - - - - - -## [6.13.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.13...@patternfly/react-charts@6.13.14) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.12...@patternfly/react-charts@6.13.13) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.11...@patternfly/react-charts@6.13.12) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.10...@patternfly/react-charts@6.13.11) (2021-02-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.9...@patternfly/react-charts@6.13.10) (2021-02-03) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.8...@patternfly/react-charts@6.13.9) (2021-02-01) - - -### Bug Fixes - -* **charts:** Bar chart remains muted with interactive legend ([#5378](https://github.com/patternfly/patternfly-react/issues/5378)) ([b83995c](https://github.com/patternfly/patternfly-react/commit/b83995c1cb47ea3641f4f65de63361764ff23a17)) - - - - - -## [6.13.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.7...@patternfly/react-charts@6.13.8) (2021-01-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.6...@patternfly/react-charts@6.13.7) (2021-01-25) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.5...@patternfly/react-charts@6.13.6) (2021-01-22) - - -### Bug Fixes - -* **Drawer:** initial width doesn't respect min/max widths ([#5313](https://github.com/patternfly/patternfly-react/issues/5313)) ([4f199c4](https://github.com/patternfly/patternfly-react/commit/4f199c4db5c3cb493d2947d871f687cc5527517c)) - - - - - -## [6.13.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.4...@patternfly/react-charts@6.13.5) (2021-01-22) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.3...@patternfly/react-charts@6.13.4) (2021-01-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.2...@patternfly/react-charts@6.13.3) (2021-01-12) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.1...@patternfly/react-charts@6.13.2) (2021-01-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.13.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.13.0...@patternfly/react-charts@6.13.1) (2021-01-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.13.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.15...@patternfly/react-charts@6.13.0) (2021-01-06) - - -### Features - -* **packages:** use react 17 ([#5111](https://github.com/patternfly/patternfly-react/issues/5111)) ([7fbafcc](https://github.com/patternfly/patternfly-react/commit/7fbafcc947c95d2bda2f4fad8f7737cf7dd3fca6)) - - - - - -## [6.12.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.14...@patternfly/react-charts@6.12.15) (2021-01-04) - - -### Bug Fixes - -* **charts:** ChartLegendTooltip shown with no data ([#5296](https://github.com/patternfly/patternfly-react/issues/5296)) ([bf05071](https://github.com/patternfly/patternfly-react/commit/bf0507184f6beb3e0d96db4f62f7303cba6cb4d4)) - - - - - -## [6.12.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.13...@patternfly/react-charts@6.12.14) (2021-01-04) - - -### Bug Fixes - -* **charts:** Incorrect colorScale prop type ([#5303](https://github.com/patternfly/patternfly-react/issues/5303)) ([8c930fb](https://github.com/patternfly/patternfly-react/commit/8c930fb0a87fdd779618e83c7276a83dd3b45262)) -* **charts:** theme font must use token value ([#5301](https://github.com/patternfly/patternfly-react/issues/5301)) ([876c17d](https://github.com/patternfly/patternfly-react/commit/876c17dad92a2ce2e33e30e0de517738091d97e9)) - - - - - -## [6.12.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.12...@patternfly/react-charts@6.12.13) (2020-12-16) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.11...@patternfly/react-charts@6.12.12) (2020-12-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.10...@patternfly/react-charts@6.12.11) (2020-12-11) - - -### Bug Fixes - -* **charts:** tooltip pointerLength error ([#5245](https://github.com/patternfly/patternfly-react/issues/5245)) ([5cdcabb](https://github.com/patternfly/patternfly-react/commit/5cdcabb42bac9d19cf485b9868e297420f44e9f5)) - - - - - -## [6.12.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.9...@patternfly/react-charts@6.12.10) (2020-12-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.8...@patternfly/react-charts@6.12.9) (2020-12-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.7...@patternfly/react-charts@6.12.8) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.6...@patternfly/react-charts@6.12.7) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.5...@patternfly/react-charts@6.12.6) (2020-12-03) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.4...@patternfly/react-charts@6.12.5) (2020-11-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.3...@patternfly/react-charts@6.12.4) (2020-11-23) - - -### Bug Fixes - -* **charts:** replace victory with victory-zoom-container ([#5179](https://github.com/patternfly/patternfly-react/issues/5179)) ([bef64a5](https://github.com/patternfly/patternfly-react/commit/bef64a5e8f8ba060061df611d028dec5f8e9adf2)) - - - - - -## [6.12.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.2...@patternfly/react-charts@6.12.3) (2020-11-23) - - -### Bug Fixes - -* **react-charts:** bump victory and move victory dep to demo app ([#5178](https://github.com/patternfly/patternfly-react/issues/5178)) ([45ec687](https://github.com/patternfly/patternfly-react/commit/45ec687506af9c0cb512feb25aa33ca2b73a7ff4)) - - - - - -## [6.12.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.1...@patternfly/react-charts@6.12.2) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.12.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.12.0...@patternfly/react-charts@6.12.1) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.12.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.9...@patternfly/react-charts@6.12.0) (2020-11-13) - - -### Features - -* **packages:** bump Victory package ([#5116](https://github.com/patternfly/patternfly-react/issues/5116)) ([a4645a2](https://github.com/patternfly/patternfly-react/commit/a4645a2fa14b2742e8957b1ae579f4350e3ddbd4)) - - - - - -## [6.11.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.8...@patternfly/react-charts@6.11.9) (2020-10-29) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.7...@patternfly/react-charts@6.11.8) (2020-10-28) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.6...@patternfly/react-charts@6.11.7) (2020-10-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.5...@patternfly/react-charts@6.11.6) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.4...@patternfly/react-charts@6.11.5) (2020-10-22) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.3...@patternfly/react-charts@6.11.4) (2020-10-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.2...@patternfly/react-charts@6.11.3) (2020-10-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.1...@patternfly/react-charts@6.11.2) (2020-10-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.11.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.11.0...@patternfly/react-charts@6.11.1) (2020-10-12) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.11.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.10.5...@patternfly/react-charts@6.11.0) (2020-10-09) - - -### Features - -* **charts:** bumped Victory pkgs from 35.0.8 to 35.2.0 ([#4992](https://github.com/patternfly/patternfly-react/issues/4992)) ([6eed4b1](https://github.com/patternfly/patternfly-react/commit/6eed4b11ef9ed495d18a46ec8082db2b40217e8d)) - - - - - -## [6.10.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.10.4...@patternfly/react-charts@6.10.5) (2020-10-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.10.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.10.3...@patternfly/react-charts@6.10.4) (2020-10-05) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.10.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.10.2...@patternfly/react-charts@6.10.3) (2020-10-01) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.10.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.10.1...@patternfly/react-charts@6.10.2) (2020-09-28) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.10.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.10.0...@patternfly/react-charts@6.10.1) (2020-09-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.10.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.9...@patternfly/react-charts@6.10.0) (2020-09-22) - - -### Features - -* **workspace:** use new doc theme ([#4840](https://github.com/patternfly/patternfly-react/issues/4840)) ([7bf451d](https://github.com/patternfly/patternfly-react/commit/7bf451d468538cc0b301fb68f0c1a8108600c24f)) - - - - - -## [6.9.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.8...@patternfly/react-charts@6.9.9) (2020-09-21) - - -### Bug Fixes - -* **charts,table:** replace or use exact lodash imports ([#4830](https://github.com/patternfly/patternfly-react/issues/4830)) ([63a8259](https://github.com/patternfly/patternfly-react/commit/63a8259c49f0eddbc699febb5f72cc5a2defb9eb)) - - - - - -## [6.9.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.7...@patternfly/react-charts@6.9.8) (2020-09-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.9.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.6...@patternfly/react-charts@6.9.7) (2020-09-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.9.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.5...@patternfly/react-charts@6.9.6) (2020-08-24) - - -### Bug Fixes - -* **docs:** use ids and h3s ([#4720](https://github.com/patternfly/patternfly-react/issues/4720)) ([a3f684f](https://github.com/patternfly/patternfly-react/commit/a3f684fa23cfce3d8e79b86206773292790cec5c)) - - - - - -## [6.9.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.4...@patternfly/react-charts@6.9.5) (2020-08-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.9.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.3...@patternfly/react-charts@6.9.4) (2020-08-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.9.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.2...@patternfly/react-charts@6.9.3) (2020-08-12) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.9.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.1...@patternfly/react-charts@6.9.2) (2020-08-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.9.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.9.0...@patternfly/react-charts@6.9.1) (2020-08-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.9.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.8.1...@patternfly/react-charts@6.9.0) (2020-08-04) - - -### Features - -* **NotificationDrawer:** Add notification drawer demo ([#4640](https://github.com/patternfly/patternfly-react/issues/4640)) ([3b9231d](https://github.com/patternfly/patternfly-react/commit/3b9231dab2fd92eb40e38d3a38ffb83562e1dbc2)) - - - - - -## [6.8.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.8.0...@patternfly/react-charts@6.8.1) (2020-08-04) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.8.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.7.1...@patternfly/react-charts@6.8.0) (2020-08-03) - - -### Features - -* **NotificationBadge:** add needs attention state and count ([#4516](https://github.com/patternfly/patternfly-react/issues/4516)) ([63c7cbf](https://github.com/patternfly/patternfly-react/commit/63c7cbf0beed5497ca7addf7fc6663229f37ab81)) - - - - - -## [6.7.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.7.0...@patternfly/react-charts@6.7.1) (2020-08-03) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.7.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.6.3...@patternfly/react-charts@6.7.0) (2020-07-30) - - -### Features - -* **charts:** update Victory packages to support OUIA props ([#4633](https://github.com/patternfly/patternfly-react/issues/4633)) ([8674066](https://github.com/patternfly/patternfly-react/commit/8674066337651f5acdf6018fa4e5cd72d37290c0)) - - - - - -## [6.6.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.6.2...@patternfly/react-charts@6.6.3) (2020-07-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.6.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.6.1...@patternfly/react-charts@6.6.2) (2020-07-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.6.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.6.0...@patternfly/react-charts@6.6.1) (2020-07-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.6.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.8...@patternfly/react-charts@6.6.0) (2020-07-16) - - -### Features - -* **FormGroup, FormSelect, TextInput, TextArea:** Add warning state ([#4554](https://github.com/patternfly/patternfly-react/issues/4554)) ([4e7f69a](https://github.com/patternfly/patternfly-react/commit/4e7f69a35abd247db99bd946a2c9bc931c335564)) - - - - - -## [6.5.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.7...@patternfly/react-charts@6.5.8) (2020-07-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.5.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.6...@patternfly/react-charts@6.5.7) (2020-07-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.5.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.5...@patternfly/react-charts@6.5.6) (2020-07-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.5.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.4...@patternfly/react-charts@6.5.5) (2020-07-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.5.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.3...@patternfly/react-charts@6.5.4) (2020-06-24) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.5.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.2...@patternfly/react-charts@6.5.3) (2020-06-23) - - -### Bug Fixes - -* **charts:** Victory package update ([#4438](https://github.com/patternfly/patternfly-react/issues/4438)) ([06d4fcb](https://github.com/patternfly/patternfly-react/commit/06d4fcb1d7857a2e9e80ec1d20a21705665c6703)) - - - - - -## [6.5.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.1...@patternfly/react-charts@6.5.2) (2020-06-22) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.5.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.5.0...@patternfly/react-charts@6.5.1) (2020-06-19) - - -### Bug Fixes - -* **charts:** set fixed line height for various text legend labels ([#4419](https://github.com/patternfly/patternfly-react/issues/4419)) ([8df0e5b](https://github.com/patternfly/patternfly-react/commit/8df0e5bca8d104d55c751561d020f2f778fd4e3a)) - - - - - -# [6.5.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.8...@patternfly/react-charts@6.5.0) (2020-06-19) - - -### Features - -* **Divider:** Add support for insets to the Divider ([#4410](https://github.com/patternfly/patternfly-react/issues/4410)) ([32916b8](https://github.com/patternfly/patternfly-react/commit/32916b89fcf631eb498ae0b64faffec756242127)) - - - - - -## [6.4.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.7...@patternfly/react-charts@6.4.8) (2020-06-18) - - -### Bug Fixes - -* **charts:** tooltip legend to use Victory's activePoints ([#4409](https://github.com/patternfly/patternfly-react/issues/4409)) ([eaecced](https://github.com/patternfly/patternfly-react/commit/eaeccedb8438bd662c9e4f407e8d0ee9e1d78dcf)) - - - - - -## [6.4.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.6...@patternfly/react-charts@6.4.7) (2020-06-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.4.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.5...@patternfly/react-charts@6.4.6) (2020-06-16) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.4.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.4...@patternfly/react-charts@6.4.5) (2020-06-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.4.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.3...@patternfly/react-charts@6.4.4) (2020-06-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.4.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.2...@patternfly/react-charts@6.4.3) (2020-06-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.4.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.1...@patternfly/react-charts@6.4.2) (2020-06-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.4.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.4.0...@patternfly/react-charts@6.4.1) (2020-06-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.12...@patternfly/react-charts@6.4.0) (2020-06-11) - - -### Features - -* **charts:** Added support for a legend tooltip ([#4371](https://github.com/patternfly/patternfly-react/issues/4371)) ([f9ec3b0](https://github.com/patternfly/patternfly-react/commit/f9ec3b007a6b9e658dcdf624d29fa3cb714db3d1)) - - - - - -## [6.3.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.11...@patternfly/react-charts@6.3.12) (2020-06-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.3.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.10...@patternfly/react-charts@6.3.11) (2020-06-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.3.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.9...@patternfly/react-charts@6.3.10) (2020-06-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.3.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.8...@patternfly/react-charts@6.3.9) (2020-06-05) - - -### Bug Fixes - -* **docs:** add upgrade guide ([#4298](https://github.com/patternfly/patternfly-react/issues/4298)) ([4ee8805](https://github.com/patternfly/patternfly-react/commit/4ee8805ab9b232ebbe280313d4ae3e53bd78fb70)) - - - - - -## [6.3.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.7...@patternfly/react-charts@6.3.8) (2020-06-05) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.3.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.6...@patternfly/react-charts@6.3.7) (2020-06-04) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.3.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.5...@patternfly/react-charts@6.3.6) (2020-06-01) - - -### Bug Fixes - -* **breakpoints:** make API consistent and appear in docs ([#4310](https://github.com/patternfly/patternfly-react/issues/4310)) ([ac1afa6](https://github.com/patternfly/patternfly-react/commit/ac1afa60067346c658fcb160534d9ddaf7dafbc6)) - - - - - -## [6.3.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.4...@patternfly/react-charts@6.3.5) (2020-05-29) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.3.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.3...@patternfly/react-charts@6.3.4) (2020-05-29) - - -### Bug Fixes - -* **charts:** Donut chart unique key warning ([#4303](https://github.com/patternfly/patternfly-react/issues/4303)) ([7f86e20](https://github.com/patternfly/patternfly-react/commit/7f86e20e04a5be9e985852cf200ff9664bf7e1a9)) -* **charts:** Update types to match latest Victory pkgs ([#4304](https://github.com/patternfly/patternfly-react/issues/4304)) ([5dfc645](https://github.com/patternfly/patternfly-react/commit/5dfc645ece1bc253e349f725241681692fd944b4)) - - - - - -## [6.3.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.2...@patternfly/react-charts@6.3.3) (2020-05-21) - - -### Bug Fixes - -* **charts:** Use Victory's createContainer instead of allowZoom prop ([#4278](https://github.com/patternfly/patternfly-react/issues/4278)) ([8c353d9](https://github.com/patternfly/patternfly-react/commit/8c353d9a5a4322984d5e564d5737e53e796928f6)) - - - - - -## [6.3.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.1...@patternfly/react-charts@6.3.2) (2020-05-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [6.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@6.3.0...@patternfly/react-charts@6.3.1) (2020-05-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [6.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.21...@patternfly/react-charts@6.3.0) (2020-05-15) - - -### Features - -* **master:** merge v4 ([#4255](https://github.com/patternfly/patternfly-react/issues/4255)) ([567c0b8](https://github.com/patternfly/patternfly-react/commit/567c0b88b10d2cd629ce380745a24dacdf9dd3d1)), closes [#3868](https://github.com/patternfly/patternfly-react/issues/3868) [#3915](https://github.com/patternfly/patternfly-react/issues/3915) [#3921](https://github.com/patternfly/patternfly-react/issues/3921) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3843](https://github.com/patternfly/patternfly-react/issues/3843) [#3884](https://github.com/patternfly/patternfly-react/issues/3884) [#3609](https://github.com/patternfly/patternfly-react/issues/3609) [#3880](https://github.com/patternfly/patternfly-react/issues/3880) [#3865](https://github.com/patternfly/patternfly-react/issues/3865) [#3894](https://github.com/patternfly/patternfly-react/issues/3894) [#3897](https://github.com/patternfly/patternfly-react/issues/3897) [#3892](https://github.com/patternfly/patternfly-react/issues/3892) [#3891](https://github.com/patternfly/patternfly-react/issues/3891) [#3908](https://github.com/patternfly/patternfly-react/issues/3908) [#3910](https://github.com/patternfly/patternfly-react/issues/3910) [#3861](https://github.com/patternfly/patternfly-react/issues/3861) [#3877](https://github.com/patternfly/patternfly-react/issues/3877) [#3916](https://github.com/patternfly/patternfly-react/issues/3916) [#3886](https://github.com/patternfly/patternfly-react/issues/3886) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3927](https://github.com/patternfly/patternfly-react/issues/3927) [#3933](https://github.com/patternfly/patternfly-react/issues/3933) [#3221](https://github.com/patternfly/patternfly-react/issues/3221) [#3873](https://github.com/patternfly/patternfly-react/issues/3873) [#3928](https://github.com/patternfly/patternfly-react/issues/3928) [#3929](https://github.com/patternfly/patternfly-react/issues/3929) [#2582](https://github.com/patternfly/patternfly-react/issues/2582) [#3296](https://github.com/patternfly/patternfly-react/issues/3296) [#3924](https://github.com/patternfly/patternfly-react/issues/3924) [#1529](https://github.com/patternfly/patternfly-react/issues/1529) [#3903](https://github.com/patternfly/patternfly-react/issues/3903) [#3904](https://github.com/patternfly/patternfly-react/issues/3904) [#3974](https://github.com/patternfly/patternfly-react/issues/3974) [#3970](https://github.com/patternfly/patternfly-react/issues/3970) [#3920](https://github.com/patternfly/patternfly-react/issues/3920) [#3945](https://github.com/patternfly/patternfly-react/issues/3945) [#3978](https://github.com/patternfly/patternfly-react/issues/3978) [#3962](https://github.com/patternfly/patternfly-react/issues/3962) [#3975](https://github.com/patternfly/patternfly-react/issues/3975) [#3906](https://github.com/patternfly/patternfly-react/issues/3906) [#3870](https://github.com/patternfly/patternfly-react/issues/3870) [#3958](https://github.com/patternfly/patternfly-react/issues/3958) [#3922](https://github.com/patternfly/patternfly-react/issues/3922) [#3985](https://github.com/patternfly/patternfly-react/issues/3985) [#3991](https://github.com/patternfly/patternfly-react/issues/3991) [#3872](https://github.com/patternfly/patternfly-react/issues/3872) [#3821](https://github.com/patternfly/patternfly-react/issues/3821) [#3807](https://github.com/patternfly/patternfly-react/issues/3807) [#3879](https://github.com/patternfly/patternfly-react/issues/3879) [#3871](https://github.com/patternfly/patternfly-react/issues/3871) [#3881](https://github.com/patternfly/patternfly-react/issues/3881) [#3826](https://github.com/patternfly/patternfly-react/issues/3826) [#3490](https://github.com/patternfly/patternfly-react/issues/3490) [#3882](https://github.com/patternfly/patternfly-react/issues/3882) [#3843](https://github.com/patternfly/patternfly-react/issues/3843) [#3884](https://github.com/patternfly/patternfly-react/issues/3884) [#3609](https://github.com/patternfly/patternfly-react/issues/3609) [#3880](https://github.com/patternfly/patternfly-react/issues/3880) [#3865](https://github.com/patternfly/patternfly-react/issues/3865) [#3894](https://github.com/patternfly/patternfly-react/issues/3894) [#3897](https://github.com/patternfly/patternfly-react/issues/3897) [#3892](https://github.com/patternfly/patternfly-react/issues/3892) [#3891](https://github.com/patternfly/patternfly-react/issues/3891) [#3908](https://github.com/patternfly/patternfly-react/issues/3908) [#3910](https://github.com/patternfly/patternfly-react/issues/3910) [#3861](https://github.com/patternfly/patternfly-react/issues/3861) [#3877](https://github.com/patternfly/patternfly-react/issues/3877) [#3916](https://github.com/patternfly/patternfly-react/issues/3916) [#3844](https://github.com/patternfly/patternfly-react/issues/3844) [#3919](https://github.com/patternfly/patternfly-react/issues/3919) [#3923](https://github.com/patternfly/patternfly-react/issues/3923) [#3838](https://github.com/patternfly/patternfly-react/issues/3838) [#3895](https://github.com/patternfly/patternfly-react/issues/3895) [#3896](https://github.com/patternfly/patternfly-react/issues/3896) [#3771](https://github.com/patternfly/patternfly-react/issues/3771) [#3940](https://github.com/patternfly/patternfly-react/issues/3940) [#3941](https://github.com/patternfly/patternfly-react/issues/3941) [#3441](https://github.com/patternfly/patternfly-react/issues/3441) [#3950](https://github.com/patternfly/patternfly-react/issues/3950) [#3642](https://github.com/patternfly/patternfly-react/issues/3642) [#3964](https://github.com/patternfly/patternfly-react/issues/3964) [#3968](https://github.com/patternfly/patternfly-react/issues/3968) [#3967](https://github.com/patternfly/patternfly-react/issues/3967) [#3971](https://github.com/patternfly/patternfly-react/issues/3971) [#3942](https://github.com/patternfly/patternfly-react/issues/3942) [#3898](https://github.com/patternfly/patternfly-react/issues/3898) [#3898](https://github.com/patternfly/patternfly-react/issues/3898) [#3976](https://github.com/patternfly/patternfly-react/issues/3976) [#3889](https://github.com/patternfly/patternfly-react/issues/3889) [#3641](https://github.com/patternfly/patternfly-react/issues/3641) [#3982](https://github.com/patternfly/patternfly-react/issues/3982) [#3979](https://github.com/patternfly/patternfly-react/issues/3979) [#3989](https://github.com/patternfly/patternfly-react/issues/3989) [#4017](https://github.com/patternfly/patternfly-react/issues/4017) [#4022](https://github.com/patternfly/patternfly-react/issues/4022) [#4014](https://github.com/patternfly/patternfly-react/issues/4014) [#4048](https://github.com/patternfly/patternfly-react/issues/4048) [#4050](https://github.com/patternfly/patternfly-react/issues/4050) [#4051](https://github.com/patternfly/patternfly-react/issues/4051) [#4058](https://github.com/patternfly/patternfly-react/issues/4058) [#4030](https://github.com/patternfly/patternfly-react/issues/4030) [#4031](https://github.com/patternfly/patternfly-react/issues/4031) [#3996](https://github.com/patternfly/patternfly-react/issues/3996) [#4001](https://github.com/patternfly/patternfly-react/issues/4001) [#4004](https://github.com/patternfly/patternfly-react/issues/4004) [#4066](https://github.com/patternfly/patternfly-react/issues/4066) [#4021](https://github.com/patternfly/patternfly-react/issues/4021) [#4061](https://github.com/patternfly/patternfly-react/issues/4061) [#4026](https://github.com/patternfly/patternfly-react/issues/4026) [#4069](https://github.com/patternfly/patternfly-react/issues/4069) [#4073](https://github.com/patternfly/patternfly-react/issues/4073) [#4036](https://github.com/patternfly/patternfly-react/issues/4036) [#4019](https://github.com/patternfly/patternfly-react/issues/4019) [#4081](https://github.com/patternfly/patternfly-react/issues/4081) [#4033](https://github.com/patternfly/patternfly-react/issues/4033) [#4065](https://github.com/patternfly/patternfly-react/issues/4065) [#4078](https://github.com/patternfly/patternfly-react/issues/4078) [#4032](https://github.com/patternfly/patternfly-react/issues/4032) [#4029](https://github.com/patternfly/patternfly-react/issues/4029) [#4064](https://github.com/patternfly/patternfly-react/issues/4064) [#4063](https://github.com/patternfly/patternfly-react/issues/4063) [#2593](https://github.com/patternfly/patternfly-react/issues/2593) [#4076](https://github.com/patternfly/patternfly-react/issues/4076) [#4099](https://github.com/patternfly/patternfly-react/issues/4099) [#4038](https://github.com/patternfly/patternfly-react/issues/4038) [#4116](https://github.com/patternfly/patternfly-react/issues/4116) [#3960](https://github.com/patternfly/patternfly-react/issues/3960) [#4121](https://github.com/patternfly/patternfly-react/issues/4121) [#4123](https://github.com/patternfly/patternfly-react/issues/4123) [#4025](https://github.com/patternfly/patternfly-react/issues/4025) [#4126](https://github.com/patternfly/patternfly-react/issues/4126) [#4122](https://github.com/patternfly/patternfly-react/issues/4122) [#4086](https://github.com/patternfly/patternfly-react/issues/4086) [#4127](https://github.com/patternfly/patternfly-react/issues/4127) [#4129](https://github.com/patternfly/patternfly-react/issues/4129) [#4111](https://github.com/patternfly/patternfly-react/issues/4111) [#4136](https://github.com/patternfly/patternfly-react/issues/4136) [#4138](https://github.com/patternfly/patternfly-react/issues/4138) [#4141](https://github.com/patternfly/patternfly-react/issues/4141) [#4145](https://github.com/patternfly/patternfly-react/issues/4145) [#4034](https://github.com/patternfly/patternfly-react/issues/4034) [#4144](https://github.com/patternfly/patternfly-react/issues/4144) [#4152](https://github.com/patternfly/patternfly-react/issues/4152) [#4158](https://github.com/patternfly/patternfly-react/issues/4158) [#4157](https://github.com/patternfly/patternfly-react/issues/4157) [#4156](https://github.com/patternfly/patternfly-react/issues/4156) [#4147](https://github.com/patternfly/patternfly-react/issues/4147) [#4159](https://github.com/patternfly/patternfly-react/issues/4159) [#4170](https://github.com/patternfly/patternfly-react/issues/4170) [#4142](https://github.com/patternfly/patternfly-react/issues/4142) [#4175](https://github.com/patternfly/patternfly-react/issues/4175) [#4176](https://github.com/patternfly/patternfly-react/issues/4176) [#4187](https://github.com/patternfly/patternfly-react/issues/4187) [#4188](https://github.com/patternfly/patternfly-react/issues/4188) [#4140](https://github.com/patternfly/patternfly-react/issues/4140) [#4193](https://github.com/patternfly/patternfly-react/issues/4193) [#4154](https://github.com/patternfly/patternfly-react/issues/4154) [#4192](https://github.com/patternfly/patternfly-react/issues/4192) [#4190](https://github.com/patternfly/patternfly-react/issues/4190) [#4199](https://github.com/patternfly/patternfly-react/issues/4199) [#4133](https://github.com/patternfly/patternfly-react/issues/4133) [#4165](https://github.com/patternfly/patternfly-react/issues/4165) [#4208](https://github.com/patternfly/patternfly-react/issues/4208) [#4212](https://github.com/patternfly/patternfly-react/issues/4212) [#4130](https://github.com/patternfly/patternfly-react/issues/4130) [#4219](https://github.com/patternfly/patternfly-react/issues/4219) [#4166](https://github.com/patternfly/patternfly-react/issues/4166) [#4202](https://github.com/patternfly/patternfly-react/issues/4202) [#4216](https://github.com/patternfly/patternfly-react/issues/4216) [#4225](https://github.com/patternfly/patternfly-react/issues/4225) [#4221](https://github.com/patternfly/patternfly-react/issues/4221) [#4146](https://github.com/patternfly/patternfly-react/issues/4146) [#3951](https://github.com/patternfly/patternfly-react/issues/3951) [#3681](https://github.com/patternfly/patternfly-react/issues/3681) [#4243](https://github.com/patternfly/patternfly-react/issues/4243) [#4220](https://github.com/patternfly/patternfly-react/issues/4220) [#4153](https://github.com/patternfly/patternfly-react/issues/4153) [#4209](https://github.com/patternfly/patternfly-react/issues/4209) [#4249](https://github.com/patternfly/patternfly-react/issues/4249) [#4239](https://github.com/patternfly/patternfly-react/issues/4239) [#4247](https://github.com/patternfly/patternfly-react/issues/4247) [#4246](https://github.com/patternfly/patternfly-react/issues/4246) [#3684](https://github.com/patternfly/patternfly-react/issues/3684) [#4223](https://github.com/patternfly/patternfly-react/issues/4223) [#4195](https://github.com/patternfly/patternfly-react/issues/4195) [#4254](https://github.com/patternfly/patternfly-react/issues/4254) -* **packages:** bump core to 4.10.21 ([#4257](https://github.com/patternfly/patternfly-react/issues/4257)) ([2e2676c](https://github.com/patternfly/patternfly-react/commit/2e2676ce6bc34f5e20231ca066d26ea4c3ac95e4)) - - - - - -## [5.3.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.20...@patternfly/react-charts@5.3.21) (2020-05-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.19...@patternfly/react-charts@5.3.20) (2020-05-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.18...@patternfly/react-charts@5.3.19) (2020-04-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.17...@patternfly/react-charts@5.3.18) (2020-04-01) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.16...@patternfly/react-charts@5.3.17) (2020-03-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.15...@patternfly/react-charts@5.3.16) (2020-03-24) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.14...@patternfly/react-charts@5.3.15) (2020-03-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.13...@patternfly/react-charts@5.3.14) (2020-03-18) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.12...@patternfly/react-charts@5.3.13) (2020-03-17) - - -### Bug Fixes - -* **core,table:** forward ref types ([#3919](https://github.com/patternfly/patternfly-react/issues/3919)) ([2210ec2](https://github.com/patternfly/patternfly-react/commit/2210ec2c142a385f85de8b0bac9c61a61521186d)) - - - - - -## [5.3.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.11...@patternfly/react-charts@5.3.12) (2020-03-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.10...@patternfly/react-charts@5.3.11) (2020-03-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.7...@patternfly/react-charts@5.3.10) (2020-03-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.6...@patternfly/react-charts@5.3.7) (2020-03-03) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.5...@patternfly/react-charts@5.3.6) (2020-02-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.4...@patternfly/react-charts@5.3.5) (2020-02-18) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.3...@patternfly/react-charts@5.3.4) (2020-02-18) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.2...@patternfly/react-charts@5.3.3) (2020-02-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.1...@patternfly/react-charts@5.3.2) (2020-02-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.3.0...@patternfly/react-charts@5.3.1) (2020-02-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [5.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.29...@patternfly/react-charts@5.3.0) (2020-02-14) - - -### Features - -* **inline-edit:** add row level inline editing feature to Table ([#3581](https://github.com/patternfly/patternfly-react/issues/3581)) ([498d49f](https://github.com/patternfly/patternfly-react/commit/498d49fcc5cc9188197ddc7cd6468907fdd8224d)) - - - - - -## [5.2.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.28...@patternfly/react-charts@5.2.29) (2020-02-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.27...@patternfly/react-charts@5.2.28) (2020-02-12) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.26...@patternfly/react-charts@5.2.27) (2020-02-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.25...@patternfly/react-charts@5.2.26) (2020-02-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.24...@patternfly/react-charts@5.2.25) (2020-02-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.23...@patternfly/react-charts@5.2.24) (2020-02-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.22...@patternfly/react-charts@5.2.23) (2020-02-04) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.21...@patternfly/react-charts@5.2.22) (2020-01-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.20...@patternfly/react-charts@5.2.21) (2020-01-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.19...@patternfly/react-charts@5.2.20) (2020-01-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.18...@patternfly/react-charts@5.2.19) (2020-01-24) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.17...@patternfly/react-charts@5.2.18) (2020-01-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.16...@patternfly/react-charts@5.2.17) (2020-01-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.15...@patternfly/react-charts@5.2.16) (2020-01-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.14...@patternfly/react-charts@5.2.15) (2020-01-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.13...@patternfly/react-charts@5.2.14) (2020-01-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.12...@patternfly/react-charts@5.2.13) (2020-01-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.11...@patternfly/react-charts@5.2.12) (2020-01-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.10...@patternfly/react-charts@5.2.11) (2020-01-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.9...@patternfly/react-charts@5.2.10) (2020-01-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.8...@patternfly/react-charts@5.2.9) (2019-12-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.7...@patternfly/react-charts@5.2.8) (2019-12-17) - - -### Bug Fixes - -* **charts:** broken Katacoda links ([#3408](https://github.com/patternfly/patternfly-react/issues/3408)) ([e6e72cd](https://github.com/patternfly/patternfly-react/commit/e6e72cd3584536e16dcda6a1c420d9e95e58f551)) - - - - - -## [5.2.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.6...@patternfly/react-charts@5.2.7) (2019-12-17) - - -### Bug Fixes - -* **charts:** update default threshold stroke width and dash array props ([#3414](https://github.com/patternfly/patternfly-react/issues/3414)) ([43ef5be](https://github.com/patternfly/patternfly-react/commit/43ef5becd5d46b60c6546b19354f684c93372b17)) - - - - - -## [5.2.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.5...@patternfly/react-charts@5.2.6) (2019-12-16) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.4...@patternfly/react-charts@5.2.5) (2019-12-12) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.3...@patternfly/react-charts@5.2.4) (2019-12-05) - - -### Bug Fixes - -* **charts:** Update interpolation examples to use monotoneX ([#3372](https://github.com/patternfly/patternfly-react/issues/3372)) ([ff96204](https://github.com/patternfly/patternfly-react/commit/ff96204f760b0d60af35c1d3d3353f1248f9a6e9)) - - - - - -## [5.2.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.2...@patternfly/react-charts@5.2.3) (2019-11-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.1...@patternfly/react-charts@5.2.2) (2019-11-21) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.2.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.2.0...@patternfly/react-charts@5.2.1) (2019-11-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [5.2.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.9...@patternfly/react-charts@5.2.0) (2019-11-19) - - -### Features - -* **charts:** update interactive legend example ([#3253](https://github.com/patternfly/patternfly-react/issues/3253)) ([018ff0c](https://github.com/patternfly/patternfly-react/commit/018ff0c9e97f611ab7f5495d81f15f233b1118c4)) - - - - - -## [5.1.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.8...@patternfly/react-charts@5.1.9) (2019-11-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.7...@patternfly/react-charts@5.1.8) (2019-11-18) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.6...@patternfly/react-charts@5.1.7) (2019-11-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.5...@patternfly/react-charts@5.1.6) (2019-11-08) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.4...@patternfly/react-charts@5.1.5) (2019-11-01) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.3...@patternfly/react-charts@5.1.4) (2019-10-31) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.2...@patternfly/react-charts@5.1.3) (2019-10-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.1...@patternfly/react-charts@5.1.2) (2019-10-25) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.1.0...@patternfly/react-charts@5.1.1) (2019-10-22) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [5.1.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.27...@patternfly/react-charts@5.1.0) (2019-10-18) - - -### Features - -* **docs:** use gatsby-theme-patternfly-org ([#3146](https://github.com/patternfly/patternfly-react/issues/3146)) ([93c843b](https://github.com/patternfly/patternfly-react/commit/93c843b)) - - - - - -## [5.0.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.26...@patternfly/react-charts@5.0.27) (2019-10-15) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.25...@patternfly/react-charts@5.0.26) (2019-10-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.24...@patternfly/react-charts@5.0.25) (2019-10-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.23...@patternfly/react-charts@5.0.24) (2019-10-14) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.22...@patternfly/react-charts@5.0.23) (2019-10-11) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.21...@patternfly/react-charts@5.0.22) (2019-10-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.20...@patternfly/react-charts@5.0.21) (2019-10-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.19...@patternfly/react-charts@5.0.20) (2019-10-09) - - -### Bug Fixes - -* **charts:** update ChartThreshold to use pf-core variable ([#3085](https://github.com/patternfly/patternfly-react/issues/3085)) ([3f77276](https://github.com/patternfly/patternfly-react/commit/3f77276)) - - - - - -## [5.0.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.18...@patternfly/react-charts@5.0.19) (2019-10-07) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.17...@patternfly/react-charts@5.0.18) (2019-10-03) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.16...@patternfly/react-charts@5.0.17) (2019-10-03) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.15...@patternfly/react-charts@5.0.16) (2019-10-03) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.14...@patternfly/react-charts@5.0.15) (2019-10-02) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.13...@patternfly/react-charts@5.0.14) (2019-10-01) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.12...@patternfly/react-charts@5.0.13) (2019-10-01) - - -### Bug Fixes - -* **charts:** modify how containers are cloned for Tippy tooltips ([#3048](https://github.com/patternfly/patternfly-react/issues/3048)) ([68f4311](https://github.com/patternfly/patternfly-react/commit/68f4311)) - - - - - -## [5.0.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.11...@patternfly/react-charts@5.0.12) (2019-09-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.10...@patternfly/react-charts@5.0.11) (2019-09-25) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.9...@patternfly/react-charts@5.0.10) (2019-09-24) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.8...@patternfly/react-charts@5.0.9) (2019-09-23) - - -### Bug Fixes - -* **charts:** add ariaDesc and ariaTitle to stack chart ([#2975](https://github.com/patternfly/patternfly-react/issues/2975)) ([339b43d](https://github.com/patternfly/patternfly-react/commit/339b43d)) - - - - - -## [5.0.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.7...@patternfly/react-charts@5.0.8) (2019-09-23) - - -### Bug Fixes - -* **charts:** replace empty tags with React.Fragment ([#2988](https://github.com/patternfly/patternfly-react/issues/2988)) ([5870729](https://github.com/patternfly/patternfly-react/commit/5870729)) - - - - - -## [5.0.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.6...@patternfly/react-charts@5.0.7) (2019-09-23) - - -### Bug Fixes - -* **charts:** missing key prop warning for ChartPie based components ([#2943](https://github.com/patternfly/patternfly-react/issues/2943)) ([219b00b](https://github.com/patternfly/patternfly-react/commit/219b00b)) - - - - - -## [5.0.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.5...@patternfly/react-charts@5.0.6) (2019-09-23) - - -### Bug Fixes - -* **charts:** add missing style and responsive props to ChartVoronoiContainer ([#2977](https://github.com/patternfly/patternfly-react/issues/2977)) ([0b10cd2](https://github.com/patternfly/patternfly-react/commit/0b10cd2)) - - - - - -## [5.0.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.4...@patternfly/react-charts@5.0.5) (2019-09-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.3...@patternfly/react-charts@5.0.4) (2019-09-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.2...@patternfly/react-charts@5.0.3) (2019-09-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.1...@patternfly/react-charts@5.0.2) (2019-09-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [5.0.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@5.0.0...@patternfly/react-charts@5.0.1) (2019-09-17) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [5.0.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.14...@patternfly/react-charts@5.0.0) (2019-09-16) - - -* Update Victory to 30.0.0 (#2883) ([b16c335](https://github.com/patternfly/patternfly-react/commit/b16c335)), closes [#2883](https://github.com/patternfly/patternfly-react/issues/2883) - - -### BREAKING CHANGES - -* upgrade to Victory 30.0.0 - - - - - -## [4.9.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.13...@patternfly/react-charts@4.9.14) (2019-09-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.12...@patternfly/react-charts@4.9.13) (2019-09-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.11...@patternfly/react-charts@4.9.12) (2019-09-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.10...@patternfly/react-charts@4.9.11) (2019-09-13) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.9...@patternfly/react-charts@4.9.10) (2019-09-10) - - -### Bug Fixes - -* **charts:** added new symbol for dash / threshold ([#2884](https://github.com/patternfly/patternfly-react/issues/2884)) ([3ab27f0](https://github.com/patternfly/patternfly-react/commit/3ab27f0)) - - - - - -## [4.9.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.8...@patternfly/react-charts@4.9.9) (2019-09-10) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.7...@patternfly/react-charts@4.9.8) (2019-09-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.6...@patternfly/react-charts@4.9.7) (2019-09-09) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.5...@patternfly/react-charts@4.9.6) (2019-09-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.4...@patternfly/react-charts@4.9.5) (2019-09-06) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.3...@patternfly/react-charts@4.9.4) (2019-09-05) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.2...@patternfly/react-charts@4.9.3) (2019-09-04) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.1...@patternfly/react-charts@4.9.2) (2019-08-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.9.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.9.0...@patternfly/react-charts@4.9.1) (2019-08-30) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [4.9.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.7...@patternfly/react-charts@4.9.0) (2019-08-30) - - -### Features - -* **chart-stack:** add monthly example ([#2625](https://github.com/patternfly/patternfly-react/issues/2625)) ([0a29e99](https://github.com/patternfly/patternfly-react/commit/0a29e99)) - - - - - -## [4.8.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.6...@patternfly/react-charts@4.8.7) (2019-08-29) - - -### Bug Fixes - -* **charts:** themeColor doc incorrectly recommends the wrong color. ([#2794](https://github.com/patternfly/patternfly-react/issues/2794)) ([9f2b38f](https://github.com/patternfly/patternfly-react/commit/9f2b38f)) - - - - - -## [4.8.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.5...@patternfly/react-charts@4.8.6) (2019-08-27) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.8.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.4...@patternfly/react-charts@4.8.5) (2019-08-26) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.8.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.3...@patternfly/react-charts@4.8.4) (2019-08-26) - - -### Bug Fixes - -* **charts:** adjust legend position for axis label ([#2763](https://github.com/patternfly/patternfly-react/issues/2763)) ([6a93c7c](https://github.com/patternfly/patternfly-react/commit/6a93c7c)) - - - - - -## [4.8.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.2...@patternfly/react-charts@4.8.3) (2019-08-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.8.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.1...@patternfly/react-charts@4.8.2) (2019-08-23) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.8.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.8.0...@patternfly/react-charts@4.8.1) (2019-08-20) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -# [4.8.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.11...@patternfly/react-charts@4.8.0) (2019-08-19) - - -### Features - -* **charts:** add bullet chart ([#2708](https://github.com/patternfly/patternfly-react/issues/2708)) ([c871fff](https://github.com/patternfly/patternfly-react/commit/c871fff)) - - - - - -## [4.7.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.10...@patternfly/react-charts@4.7.11) (2019-08-19) - -**Note:** Version bump only for package @patternfly/react-charts - - - - - -## [4.7.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.9...@patternfly/react-charts@4.7.10) (2019-08-19) - +# [8.6.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.1-prerelease.0...@patternfly/react-charts@8.6.0-prerelease.1) (2026-05-26) ### Bug Fixes -* **charts:** clean up tests and doc ([#2707](https://github.com/patternfly/patternfly-react/issues/2707)) ([7e8350b](https://github.com/patternfly/patternfly-react/commit/7e8350b)) - - - - - -## [4.7.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.8...@patternfly/react-charts@4.7.9) (2019-08-16) - -**Note:** Version bump only for package @patternfly/react-charts - +- updated to do 6.6.0 prereleases. ([#12434](https://github.com/patternfly/patternfly-react/issues/12434)) ([6e09ce8](https://github.com/patternfly/patternfly-react/commit/6e09ce8322ff13354991d901782231d437249aa6)) - - - -## [4.7.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.7...@patternfly/react-charts@4.7.8) (2019-08-15) +## [8.5.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0...@patternfly/react-charts@8.5.1-prerelease.0) (2026-05-21) **Note:** Version bump only for package @patternfly/react-charts +# 8.5.0 (2026-05-20) +### Reverts +- Revert "chore(release): releasing packages [ci skip]" ([7185856](https://github.com/patternfly/patternfly-react/commit/7185856d4985da5129bbabd6c460049e7048dd2a)) - -## [4.7.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.6...@patternfly/react-charts@4.7.7) (2019-08-13) +# [8.5.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.31...@patternfly/react-charts@8.5.0-prerelease.32) (2026-05-19) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.7.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.5...@patternfly/react-charts@4.7.6) (2019-08-12) +# [8.5.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.30...@patternfly/react-charts@8.5.0-prerelease.31) (2026-05-14) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.7.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.4...@patternfly/react-charts@4.7.5) (2019-08-09) +# [8.5.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.29...@patternfly/react-charts@8.5.0-prerelease.30) (2026-05-13) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.7.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.3...@patternfly/react-charts@4.7.4) (2019-08-05) +# [8.5.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.28...@patternfly/react-charts@8.5.0-prerelease.29) (2026-05-12) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.7.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.2...@patternfly/react-charts@4.7.3) (2019-08-02) - - -### Bug Fixes - -* **Chart Themes:** Fix missing fill and stroke colors for area and line charts ([#2626](https://github.com/patternfly/patternfly-react/issues/2626)) ([9d3138c](https://github.com/patternfly/patternfly-react/commit/9d3138c)), closes [#2624](https://github.com/patternfly/patternfly-react/issues/2624) - - - - - -## [4.7.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.1...@patternfly/react-charts@4.7.2) (2019-07-25) - - -### Bug Fixes - -* **chart:** ensure dynamic chart size is never less than zero ([#2590](https://github.com/patternfly/patternfly-react/issues/2590)) ([9e9b48e](https://github.com/patternfly/patternfly-react/commit/9e9b48e)) - - - - - -## [4.7.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.7.0...@patternfly/react-charts@4.7.1) (2019-07-24) - - -### Bug Fixes - -* **charts:** use vars to enable Red Hat fonts ([#2584](https://github.com/patternfly/patternfly-react/issues/2584)) ([d555f2a](https://github.com/patternfly/patternfly-react/commit/d555f2a)) - - - - - -# [4.7.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.6.5...@patternfly/react-charts@4.7.0) (2019-07-22) - +# [8.5.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.27...@patternfly/react-charts@8.5.0-prerelease.28) (2026-05-12) ### Features -* **charts:** added new mutil-color theme for ordered charts ([#2552](https://github.com/patternfly/patternfly-react/issues/2552)) ([8ab3844](https://github.com/patternfly/patternfly-react/commit/8ab3844)) +- **react-charts:** add high contrast ([#12419](https://github.com/patternfly/patternfly-react/issues/12419)) ([e9c801c](https://github.com/patternfly/patternfly-react/commit/e9c801c84067fb9ed42d10d19deadf8dfca55289)) - - - - -## [4.6.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.6.4...@patternfly/react-charts@4.6.5) (2019-07-22) +# [8.5.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.26...@patternfly/react-charts@8.5.0-prerelease.27) (2026-05-08) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.6.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.6.3...@patternfly/react-charts@4.6.4) (2019-07-18) - - -### Bug Fixes - -* **charts:** add individual padding vars for donut charts ([#2529](https://github.com/patternfly/patternfly-react/issues/2529)) ([771eee8](https://github.com/patternfly/patternfly-react/commit/771eee8)) - - - - - -## [4.6.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.6.2...@patternfly/react-charts@4.6.3) (2019-07-17) +# [8.5.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.25...@patternfly/react-charts@8.5.0-prerelease.26) (2026-05-08) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.6.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.6.1...@patternfly/react-charts@4.6.2) (2019-07-16) +# [8.5.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.24...@patternfly/react-charts@8.5.0-prerelease.25) (2026-05-07) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.6.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.6.0...@patternfly/react-charts@4.6.1) (2019-07-15) +# [8.5.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.23...@patternfly/react-charts@8.5.0-prerelease.24) (2026-04-28) **Note:** Version bump only for package @patternfly/react-charts - - - - -# [4.6.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.5.2...@patternfly/react-charts@4.6.0) (2019-07-12) - - -### Features - -* **charts:** added ariaLabelDesc and ariaLabelTitle props ([#2500](https://github.com/patternfly/patternfly-react/issues/2500)) ([0e5ac2b](https://github.com/patternfly/patternfly-react/commit/0e5ac2b)) - - - - - -## [4.5.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.5.1...@patternfly/react-charts@4.5.2) (2019-07-11) - - -### Bug Fixes - -* **charts:** adjust pf-core vars & add tooltip examples ([#2497](https://github.com/patternfly/patternfly-react/issues/2497)) ([e19eb37](https://github.com/patternfly/patternfly-react/commit/e19eb37)) - - - - - -## [4.5.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.5.0...@patternfly/react-charts@4.5.1) (2019-07-10) +# [8.5.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.22...@patternfly/react-charts@8.5.0-prerelease.23) (2026-04-24) **Note:** Version bump only for package @patternfly/react-charts - - - - -# [4.5.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.17...@patternfly/react-charts@4.5.0) (2019-07-10) - - -### Features - -* **charts:** adds bottom-left legend position ([#2442](https://github.com/patternfly/patternfly-react/issues/2442)) ([1f52911](https://github.com/patternfly/patternfly-react/commit/1f52911)) - - - - - -## [4.4.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.16...@patternfly/react-charts@4.4.17) (2019-07-10) - - -### Bug Fixes - -* **ChartDonut:** Replaced prop `titleComponent` if function `getSubTitle` by `subTitleComponent`. ([#2488](https://github.com/patternfly/patternfly-react/issues/2488)) ([18190a4](https://github.com/patternfly/patternfly-react/commit/18190a4)), closes [#2486](https://github.com/patternfly/patternfly-react/issues/2486) - - - - - -## [4.4.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.15...@patternfly/react-charts@4.4.16) (2019-07-09) +# [8.5.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.21...@patternfly/react-charts@8.5.0-prerelease.22) (2026-04-24) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.14...@patternfly/react-charts@4.4.15) (2019-07-09) - - -### Bug Fixes - -* **charts:** update pf-core vars ([#2480](https://github.com/patternfly/patternfly-react/issues/2480)) ([6c36ec7](https://github.com/patternfly/patternfly-react/commit/6c36ec7)) - - - - - -## [4.4.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.13...@patternfly/react-charts@4.4.14) (2019-07-08) - - -### Bug Fixes - -* **build:** make pf3/pf4 build on windows ([#2471](https://github.com/patternfly/patternfly-react/issues/2471)) ([5bbc4a2](https://github.com/patternfly/patternfly-react/commit/5bbc4a2)) - - - - - -## [4.4.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.12...@patternfly/react-charts@4.4.13) (2019-07-08) +# [8.5.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.20...@patternfly/react-charts@8.5.0-prerelease.21) (2026-04-20) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.11...@patternfly/react-charts@4.4.12) (2019-07-06) +# [8.5.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.19...@patternfly/react-charts@8.5.0-prerelease.20) (2026-04-13) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.10...@patternfly/react-charts@4.4.11) (2019-07-05) +# [8.5.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.18...@patternfly/react-charts@8.5.0-prerelease.19) (2026-04-06) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.9...@patternfly/react-charts@4.4.10) (2019-07-05) - - -### Bug Fixes - -* **charts:** remove invalid pf-core var ([#2463](https://github.com/patternfly/patternfly-react/issues/2463)) ([1d37eda](https://github.com/patternfly/patternfly-react/commit/1d37eda)) - - - - - -## [4.4.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.8...@patternfly/react-charts@4.4.9) (2019-07-05) +# [8.5.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.17...@patternfly/react-charts@8.5.0-prerelease.18) (2026-04-01) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.7...@patternfly/react-charts@4.4.8) (2019-07-03) +# [8.5.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.16...@patternfly/react-charts@8.5.0-prerelease.17) (2026-03-27) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.6...@patternfly/react-charts@4.4.7) (2019-07-02) - - -### Bug Fixes - -* **Chart:** Fix runtime errors related to theme padding ([#2430](https://github.com/patternfly/patternfly-react/issues/2430)) ([a4d9f75](https://github.com/patternfly/patternfly-react/commit/a4d9f75)), closes [#2429](https://github.com/patternfly/patternfly-react/issues/2429) - - - - - -## [4.4.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.5...@patternfly/react-charts@4.4.6) (2019-06-28) +# [8.5.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.15...@patternfly/react-charts@8.5.0-prerelease.16) (2026-03-19) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.4...@patternfly/react-charts@4.4.5) (2019-06-27) - - -### Bug Fixes - -* **charts:** adds sparkline example and interpolation to area examples ([#2373](https://github.com/patternfly/patternfly-react/issues/2373)) ([ac68f3f](https://github.com/patternfly/patternfly-react/commit/ac68f3f)) - - - - - -## [4.4.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.3...@patternfly/react-charts@4.4.4) (2019-06-25) +# [8.5.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.14...@patternfly/react-charts@8.5.0-prerelease.15) (2026-02-24) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.2...@patternfly/react-charts@4.4.3) (2019-06-25) - - -### Bug Fixes - -* **charts:** ensure thresholds are sorted ([#2341](https://github.com/patternfly/patternfly-react/issues/2341)) ([f44d4c5](https://github.com/patternfly/patternfly-react/commit/f44d4c5)) - - - - - -## [4.4.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.1...@patternfly/react-charts@4.4.2) (2019-06-21) +# [8.5.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.13...@patternfly/react-charts@8.5.0-prerelease.14) (2026-02-18) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.4.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.4.0...@patternfly/react-charts@4.4.1) (2019-06-20) +# [8.5.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.12...@patternfly/react-charts@8.5.0-prerelease.13) (2026-02-05) **Note:** Version bump only for package @patternfly/react-charts - - - - -# [4.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.7...@patternfly/react-charts@4.4.0) (2019-06-20) - - -### Features - -* **charts:** add invert prop for reversing thresholds ([#2294](https://github.com/patternfly/patternfly-react/issues/2294)) ([7617e6a](https://github.com/patternfly/patternfly-react/commit/7617e6a)) - - - - - -## [4.3.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.6...@patternfly/react-charts@4.3.7) (2019-06-18) +# [8.5.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.11...@patternfly/react-charts@8.5.0-prerelease.12) (2026-01-28) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.3.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.5...@patternfly/react-charts@4.3.6) (2019-06-18) +# [8.5.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.10...@patternfly/react-charts@8.5.0-prerelease.11) (2026-01-09) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [4.3.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.4...@patternfly/react-charts@4.3.5) (2019-06-18) +# [8.5.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.9...@patternfly/react-charts@8.5.0-prerelease.10) (2025-12-17) **Note:** Version bump only for package @patternfly/react-charts +# [8.5.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.6...@patternfly/react-charts@8.5.0-prerelease.9) (2025-12-16) +**Note:** Version bump only for package @patternfly/react-charts - - -## [4.3.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.2...@patternfly/react-charts@4.3.4) (2019-06-18) - - -### Bug Fixes - -* **ChartDonutThreshold:** Don't show static threshold donut tooltips by default. ([#2270](https://github.com/patternfly/patternfly-react/issues/2270)) ([7d9bd16](https://github.com/patternfly/patternfly-react/commit/7d9bd16)) - - - - - -## [4.3.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.2...@patternfly/react-charts@4.3.3) (2019-06-18) - +# [8.5.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.5...@patternfly/react-charts@8.5.0-prerelease.6) (2025-11-14) ### Bug Fixes -* **ChartDonutThreshold:** Don't show static threshold donut tooltips by default. ([#2270](https://github.com/patternfly/patternfly-react/issues/2270)) ([7d9bd16](https://github.com/patternfly/patternfly-react/commit/7d9bd16)) +- Moves items to new nav. ([#12013](https://github.com/patternfly/patternfly-react/issues/12013)) ([ddd0696](https://github.com/patternfly/patternfly-react/commit/ddd0696796134c7d0f9583ce56e26b0df47156cb)) +# [8.5.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.4...@patternfly/react-charts@8.5.0-prerelease.5) (2025-11-12) +**Note:** Version bump only for package @patternfly/react-charts +# [8.5.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.3...@patternfly/react-charts@8.5.0-prerelease.4) (2025-11-06) +**Note:** Version bump only for package @patternfly/react-charts -## [4.3.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.1...@patternfly/react-charts@4.3.2) (2019-06-14) +# [8.5.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.2...@patternfly/react-charts@8.5.0-prerelease.3) (2025-11-05) **Note:** Version bump only for package @patternfly/react-charts +# [8.5.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.5.0-prerelease.1...@patternfly/react-charts@8.5.0-prerelease.2) (2025-10-31) +**Note:** Version bump only for package @patternfly/react-charts +# [8.5.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.4.0...@patternfly/react-charts@8.5.0-prerelease.1) (2025-10-30) +**Note:** Version bump only for package @patternfly/react-charts -## [4.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.3.0...@patternfly/react-charts@4.3.1) (2019-06-14) +# [8.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.4.0-prerelease.4...@patternfly/react-charts@8.4.0) (2025-10-16) **Note:** Version bump only for package @patternfly/react-charts +# [8.4.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.4.0-prerelease.3...@patternfly/react-charts@8.4.0-prerelease.4) (2025-10-16) +**Note:** Version bump only for package @patternfly/react-charts +# [8.4.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.4.0-prerelease.2...@patternfly/react-charts@8.4.0-prerelease.3) (2025-10-01) +### Bug Fixes -# [4.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.2.0...@patternfly/react-charts@4.3.0) (2019-06-13) +- Bumped echarts and core. ([#12023](https://github.com/patternfly/patternfly-react/issues/12023)) ([1d4d075](https://github.com/patternfly/patternfly-react/commit/1d4d075730c3645394c774bfc5233ea786e29e43)) +# [8.4.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.1-prerelease.3...@patternfly/react-charts@8.4.0-prerelease.2) (2025-09-26) -### Features +### Bug Fixes -* **build:** add source maps ([#2142](https://github.com/patternfly/patternfly-react/issues/2142)) ([5076c48](https://github.com/patternfly/patternfly-react/commit/5076c48)) +- updated to 6.4.0-prerelease ([df46ac6](https://github.com/patternfly/patternfly-react/commit/df46ac6bed381eb3e01e5573f77d79301b02b7fa)) +## [8.3.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.1-prerelease.2...@patternfly/react-charts@8.3.1-prerelease.3) (2025-09-26) +**Note:** Version bump only for package @patternfly/react-charts +## [8.3.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.1-prerelease.1...@patternfly/react-charts@8.3.1-prerelease.2) (2025-09-24) +**Note:** Version bump only for package @patternfly/react-charts -# 4.2.0 (2019-06-13) +## [8.3.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.1-prerelease.0...@patternfly/react-charts@8.3.1-prerelease.1) (2025-09-05) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +## [8.3.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0...@patternfly/react-charts@8.3.1-prerelease.0) (2025-07-28) -* **charts:** labels should use the overpass font ([#2232](https://github.com/patternfly/patternfly-react/issues/2232)) ([7b4e100](https://github.com/patternfly/patternfly-react/commit/7b4e100)) +**Note:** Version bump only for package @patternfly/react-charts +# 8.3.0 (2025-07-22) -### Features +**Note:** Version bump only for package @patternfly/react-charts -* **react-core:** allow dynamic rendering of anchor components ([#2117](https://github.com/patternfly/patternfly-react/issues/2117)) ([c1c3be9](https://github.com/patternfly/patternfly-react/commit/c1c3be9)) +# [8.3.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.4.0-prerelease.0...@patternfly/react-charts@8.3.0-prerelease.22) (2025-07-22) +### Reverts +- Revert "chore(release): releasing packages [ci skip]" ([40999d7](https://github.com/patternfly/patternfly-react/commit/40999d70a7a3aeadbe8f40fe96bb01ab3a6219d4)) +# [8.3.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.20...@patternfly/react-charts@8.3.0-prerelease.21) (2025-07-18) +**Note:** Version bump only for package @patternfly/react-charts -## [4.1.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.1.4...@patternfly/react-charts@4.1.5) (2019-06-11) +# [8.3.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.19...@patternfly/react-charts@8.3.0-prerelease.20) (2025-07-17) **Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.18...@patternfly/react-charts@8.3.0-prerelease.19) (2025-07-11) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.17...@patternfly/react-charts@8.3.0-prerelease.18) (2025-07-02) +**Note:** Version bump only for package @patternfly/react-charts -## [4.1.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.1.3...@patternfly/react-charts@4.1.4) (2019-06-10) +# [8.3.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.16...@patternfly/react-charts@8.3.0-prerelease.17) (2025-06-23) **Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.15...@patternfly/react-charts@8.3.0-prerelease.16) (2025-06-20) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.14...@patternfly/react-charts@8.3.0-prerelease.15) (2025-06-18) +**Note:** Version bump only for package @patternfly/react-charts -## [4.1.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.1.2...@patternfly/react-charts@4.1.3) (2019-06-10) +# [8.3.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.13...@patternfly/react-charts@8.3.0-prerelease.14) (2025-06-17) **Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.12...@patternfly/react-charts@8.3.0-prerelease.13) (2025-06-13) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.11...@patternfly/react-charts@8.3.0-prerelease.12) (2025-06-13) +**Note:** Version bump only for package @patternfly/react-charts -## 4.1.2 (2019-06-10) +# [8.3.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.10...@patternfly/react-charts@8.3.0-prerelease.11) (2025-06-11) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +# [8.3.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.9...@patternfly/react-charts@8.3.0-prerelease.10) (2025-05-21) -* **charts:** align label vertically and add donutHeight/Width defaults ([#2193](https://github.com/patternfly/patternfly-react/issues/2193)) ([59aadfc](https://github.com/patternfly/patternfly-react/commit/59aadfc)) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.8...@patternfly/react-charts@8.3.0-prerelease.9) (2025-05-20) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.7...@patternfly/react-charts@8.3.0-prerelease.8) (2025-05-20) +**Note:** Version bump only for package @patternfly/react-charts -## [4.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.1.0...@patternfly/react-charts@4.1.1) (2019-06-05) +# [8.3.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.6...@patternfly/react-charts@8.3.0-prerelease.7) (2025-05-19) **Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.5...@patternfly/react-charts@8.3.0-prerelease.6) (2025-05-19) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.4...@patternfly/react-charts@8.3.0-prerelease.5) (2025-05-15) +**Note:** Version bump only for package @patternfly/react-charts -# 4.1.0 (2019-06-05) +# [8.3.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.3...@patternfly/react-charts@8.3.0-prerelease.4) (2025-05-15) +**Note:** Version bump only for package @patternfly/react-charts -### Features +# [8.3.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.2...@patternfly/react-charts@8.3.0-prerelease.3) (2025-05-15) -* **background image:** Convert background image to typescript ([#2070](https://github.com/patternfly/patternfly-react/issues/2070)) ([d4ae6db](https://github.com/patternfly/patternfly-react/commit/d4ae6db)) -* **VictoryZoomContainer:** Give examples of Victory Zoom component to allow zo… ([#1879](https://github.com/patternfly/patternfly-react/issues/1879)) ([235c174](https://github.com/patternfly/patternfly-react/commit/235c174)), closes [#1715](https://github.com/patternfly/patternfly-react/issues/1715) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.3.0-prerelease.1...@patternfly/react-charts@8.3.0-prerelease.2) (2025-04-29) +**Note:** Version bump only for package @patternfly/react-charts +# [8.3.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.1-prerelease.1...@patternfly/react-charts@8.3.0-prerelease.1) (2025-04-24) +**Note:** Version bump only for package @patternfly/react-charts -## [4.0.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.0.1...@patternfly/react-charts@4.0.2) (2019-06-04) +## [8.2.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.1-prerelease.0...@patternfly/react-charts@8.2.1-prerelease.1) (2025-04-21) +### Features -### Bug Fixes +- **version:** testing react 19 ([#11754](https://github.com/patternfly/patternfly-react/issues/11754)) ([b981588](https://github.com/patternfly/patternfly-react/commit/b9815886da3adc7a96bc2d48adacf86e8a752e61)) -* **charts:** Chart & ChartStack to use ReactNode as children type ([#2155](https://github.com/patternfly/patternfly-react/issues/2155)) ([0b0a828](https://github.com/patternfly/patternfly-react/commit/0b0a828)) +## [8.2.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0...@patternfly/react-charts@8.2.1-prerelease.0) (2025-04-14) +**Note:** Version bump only for package @patternfly/react-charts +# 8.2.0 (2025-04-07) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.27...@patternfly/react-charts@8.2.0-prerelease.28) (2025-04-01) -## [4.0.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@4.0.0...@patternfly/react-charts@4.0.1) (2019-06-04) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.26...@patternfly/react-charts@8.2.0-prerelease.27) (2025-03-26) ### Bug Fixes -* **charts:** remove ChartThemeDefinition export from index.ts ([#2149](https://github.com/patternfly/patternfly-react/issues/2149)) ([9929698](https://github.com/patternfly/patternfly-react/commit/9929698)) - - +- **charts:** tooltip must call value formatter ([#11711](https://github.com/patternfly/patternfly-react/issues/11711)) ([ec4d8fc](https://github.com/patternfly/patternfly-react/commit/ec4d8fc5647b808420b3b975804e1348f14b1223)) +# [8.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.25...@patternfly/react-charts@8.2.0-prerelease.26) (2025-03-20) +### Features -# [4.0.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.7...@patternfly/react-charts@4.0.0) (2019-06-04) +- **charts:** Sankey and Line charts, based on Apache ECharts ([#11616](https://github.com/patternfly/patternfly-react/issues/11616)) ([f2479b1](https://github.com/patternfly/patternfly-react/commit/f2479b10dc6a96e97bfa1b0bb4bc3da789b9e93b)) +# [8.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.24...@patternfly/react-charts@8.2.0-prerelease.25) (2025-03-11) -### chore +**Note:** Version bump only for package @patternfly/react-charts -* **charts:** major bump react-charts ([#2143](https://github.com/patternfly/patternfly-react/issues/2143)) ([90b334e](https://github.com/patternfly/patternfly-react/commit/90b334e)) +# [8.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.23...@patternfly/react-charts@8.2.0-prerelease.24) (2025-03-10) +**Note:** Version bump only for package @patternfly/react-charts -### BREAKING CHANGES +# [8.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.22...@patternfly/react-charts@8.2.0-prerelease.23) (2025-03-10) -* **charts:** - Changed default Chart padding property to show axis -- Refactored ChartTheme colors and utils for donut utilization theme -- ChartLegend now defaults to be responsive +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.21...@patternfly/react-charts@8.2.0-prerelease.22) (2025-03-06) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.20...@patternfly/react-charts@8.2.0-prerelease.21) (2025-03-05) +**Note:** Version bump only for package @patternfly/react-charts -## [3.6.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.6...@patternfly/react-charts@3.6.7) (2019-06-03) +# [8.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.19...@patternfly/react-charts@8.2.0-prerelease.20) (2025-03-03) **Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.18...@patternfly/react-charts@8.2.0-prerelease.19) (2025-02-27) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.17...@patternfly/react-charts@8.2.0-prerelease.18) (2025-02-25) -## [3.6.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.5...@patternfly/react-charts@3.6.6) (2019-06-03) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.16...@patternfly/react-charts@8.2.0-prerelease.17) (2025-02-24) -### Performance Improvements +**Note:** Version bump only for package @patternfly/react-charts -* **charts:** breaking change bump ([#2141](https://github.com/patternfly/patternfly-react/issues/2141)) ([10296da](https://github.com/patternfly/patternfly-react/commit/10296da)) +# [8.2.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.15...@patternfly/react-charts@8.2.0-prerelease.16) (2025-02-20) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.14...@patternfly/react-charts@8.2.0-prerelease.15) (2025-02-14) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.13...@patternfly/react-charts@8.2.0-prerelease.14) (2025-02-12) -## [3.6.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.4...@patternfly/react-charts@3.6.5) (2019-06-03) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.12...@patternfly/react-charts@8.2.0-prerelease.13) (2025-01-28) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +# [8.2.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.11...@patternfly/react-charts@8.2.0-prerelease.12) (2025-01-24) -* **Charts:** Fix themes for bar chart default colors ([#2112](https://github.com/patternfly/patternfly-react/issues/2112)) ([7b290ab](https://github.com/patternfly/patternfly-react/commit/7b290ab)), closes [#2111](https://github.com/patternfly/patternfly-react/issues/2111) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.10...@patternfly/react-charts@8.2.0-prerelease.11) (2025-01-24) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.9...@patternfly/react-charts@8.2.0-prerelease.10) (2025-01-23) +**Note:** Version bump only for package @patternfly/react-charts -## [3.6.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.3...@patternfly/react-charts@3.6.4) (2019-05-30) +# [8.2.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.8...@patternfly/react-charts@8.2.0-prerelease.9) (2025-01-21) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +# [8.2.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.7...@patternfly/react-charts@8.2.0-prerelease.8) (2025-01-17) -* **charts:** Add defaults for component props ([#2103](https://github.com/patternfly/patternfly-react/issues/2103)) ([ca98322](https://github.com/patternfly/patternfly-react/commit/ca98322)) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.6...@patternfly/react-charts@8.2.0-prerelease.7) (2025-01-15) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.5...@patternfly/react-charts@8.2.0-prerelease.6) (2025-01-14) +**Note:** Version bump only for package @patternfly/react-charts -## [3.6.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.2...@patternfly/react-charts@3.6.3) (2019-05-29) +# [8.2.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.4...@patternfly/react-charts@8.2.0-prerelease.5) (2025-01-14) **Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.3...@patternfly/react-charts@8.2.0-prerelease.4) (2025-01-10) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.2...@patternfly/react-charts@8.2.0-prerelease.3) (2025-01-08) +**Note:** Version bump only for package @patternfly/react-charts -## [3.6.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.1...@patternfly/react-charts@3.6.2) (2019-05-29) - +# [8.2.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.1...@patternfly/react-charts@8.2.0-prerelease.2) (2025-01-07) ### Bug Fixes -* **docs:** use frontmatter for what props to show in docs ([#2072](https://github.com/patternfly/patternfly-react/issues/2072)) ([20e6b12](https://github.com/patternfly/patternfly-react/commit/20e6b12)) +- **charts:** fix Victory 37.3.4 issues ([#11356](https://github.com/patternfly/patternfly-react/issues/11356)) ([9c88a1c](https://github.com/patternfly/patternfly-react/commit/9c88a1c14784dd4e83f03528734366883ad5c133)) +# [8.2.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.2.0-prerelease.0...@patternfly/react-charts@8.2.0-prerelease.1) (2025-01-06) +**Note:** Version bump only for package @patternfly/react-charts +# [8.2.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.1-prerelease.0...@patternfly/react-charts@8.2.0-prerelease.0) (2025-01-06) +**Note:** Version bump only for package @patternfly/react-charts -## [3.6.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.6.0...@patternfly/react-charts@3.6.1) (2019-05-29) +## [8.1.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0...@patternfly/react-charts@8.1.1-prerelease.0) (2024-12-18) **Note:** Version bump only for package @patternfly/react-charts +# 8.1.0 (2024-12-16) +### Bug Fixes +- Update promote.sh to release 6.1.0 ([2b5106f](https://github.com/patternfly/patternfly-react/commit/2b5106ff88ce207d4a9ed2066fd390009e81fb79)) +# [8.1.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.17...@patternfly/react-charts@8.1.0-prerelease.18) (2024-12-10) -# [3.6.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.5.2...@patternfly/react-charts@3.6.0) (2019-05-28) - +**Note:** Version bump only for package @patternfly/react-charts -### Features +# [8.1.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.16...@patternfly/react-charts@8.1.0-prerelease.17) (2024-12-04) -* **charts:** add typescript support to react-charts ([#2081](https://github.com/patternfly/patternfly-react/issues/2081)) ([42c2845](https://github.com/patternfly/patternfly-react/commit/42c2845)) +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.15...@patternfly/react-charts@8.1.0-prerelease.16) (2024-11-25) +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.14...@patternfly/react-charts@8.1.0-prerelease.15) (2024-11-20) +**Note:** Version bump only for package @patternfly/react-charts -## [3.5.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.5.1...@patternfly/react-charts@3.5.2) (2019-05-24) +# [8.1.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.13...@patternfly/react-charts@8.1.0-prerelease.14) (2024-11-19) **Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.12...@patternfly/react-charts@8.1.0-prerelease.13) (2024-11-19) +**Note:** Version bump only for package @patternfly/react-charts + +# [8.1.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.11...@patternfly/react-charts@8.1.0-prerelease.12) (2024-11-19) +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.10...@patternfly/react-charts@8.1.0-prerelease.11) (2024-11-19) -## [3.5.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.5.0...@patternfly/react-charts@3.5.1) (2019-05-23) +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.9...@patternfly/react-charts@8.1.0-prerelease.10) (2024-11-18) ### Bug Fixes -* **Charts:** Fix type definitions for chart themes ([#2062](https://github.com/patternfly/patternfly-react/issues/2062)) ([63ff308](https://github.com/patternfly/patternfly-react/commit/63ff308)), closes [#2061](https://github.com/patternfly/patternfly-react/issues/2061) +- **deps:** update dependency tslib to ^2.8.1 ([#11222](https://github.com/patternfly/patternfly-react/issues/11222)) ([7c90e9b](https://github.com/patternfly/patternfly-react/commit/7c90e9bff23083f097e78246570be60dacfb27c0)) +# [8.1.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.8...@patternfly/react-charts@8.1.0-prerelease.9) (2024-11-18) +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.7...@patternfly/react-charts@8.1.0-prerelease.8) (2024-11-15) +**Note:** Version bump only for package @patternfly/react-charts -# 3.5.0 (2019-05-21) +# [8.1.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.6...@patternfly/react-charts@8.1.0-prerelease.7) (2024-11-15) +**Note:** Version bump only for package @patternfly/react-charts -### Features +# [8.1.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.5...@patternfly/react-charts@8.1.0-prerelease.6) (2024-11-15) -* **ts:** convert aboutmodal to TS ([#1968](https://github.com/patternfly/patternfly-react/issues/1968)) ([7dd9526](https://github.com/patternfly/patternfly-react/commit/7dd9526)) +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.4...@patternfly/react-charts@8.1.0-prerelease.5) (2024-11-14) +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.3...@patternfly/react-charts@8.1.0-prerelease.4) (2024-11-14) +**Note:** Version bump only for package @patternfly/react-charts -## [3.4.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.4.5...@patternfly/react-charts@3.4.6) (2019-05-09) +# [8.1.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.2...@patternfly/react-charts@8.1.0-prerelease.3) (2024-11-13) **Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.1...@patternfly/react-charts@8.1.0-prerelease.2) (2024-11-06) + +**Note:** Version bump only for package @patternfly/react-charts +# [8.1.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.1.0-prerelease.0...@patternfly/react-charts@8.1.0-prerelease.1) (2024-10-30) +### Bug Fixes +- **charts:** update font-family ([#11122](https://github.com/patternfly/patternfly-react/issues/11122)) ([e2d9e39](https://github.com/patternfly/patternfly-react/commit/e2d9e3922801f96336993037dda91eeb150c465e)) -## [3.4.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.4.4...@patternfly/react-charts@3.4.5) (2019-05-07) +# 8.1.0-prerelease.0 (2024-10-24) **Note:** Version bump only for package @patternfly/react-charts +# 8.0.0 (2024-10-24) + +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.14...@patternfly/react-charts@8.0.0-prerelease.15) (2024-10-23) +### Bug Fixes +- **charts:** update Victory packages to be optional peer dependencies ([#11128](https://github.com/patternfly/patternfly-react/issues/11128)) ([09a8f38](https://github.com/patternfly/patternfly-react/commit/09a8f38fbe2d8c1d2fb4d607440a8f14271224c8)) -## [3.4.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.4.3...@patternfly/react-charts@3.4.4) (2019-05-07) +# [8.0.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.13...@patternfly/react-charts@8.0.0-prerelease.14) (2024-10-02) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +# [8.0.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.12...@patternfly/react-charts@8.0.0-prerelease.13) (2024-09-30) -* **types:** Update @types/victory package to latest ([#1899](https://github.com/patternfly/patternfly-react/issues/1899)) ([d3e2ec7](https://github.com/patternfly/patternfly-react/commit/d3e2ec7)), closes [#1898](https://github.com/patternfly/patternfly-react/issues/1898) +### Features +- **charts:** import charts from @patternfly/react-charts/victory ([#11091](https://github.com/patternfly/patternfly-react/issues/11091)) ([2d3921b](https://github.com/patternfly/patternfly-react/commit/2d3921b7dab1733fce0a640e7d64d01fc21dbac1)) +# [8.0.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.11...@patternfly/react-charts@8.0.0-prerelease.12) (2024-09-26) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.10...@patternfly/react-charts@8.0.0-prerelease.11) (2024-09-24) -## 3.4.3 (2019-05-06) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.9...@patternfly/react-charts@8.0.0-prerelease.10) (2024-09-19) ### Bug Fixes -* **charts:** Fix chart font stack to use PatternFly core sans-serif font stack ([#1865](https://github.com/patternfly/patternfly-react/issues/1865)) ([f2b4cc7](https://github.com/patternfly/patternfly-react/commit/f2b4cc7)), closes [#1864](https://github.com/patternfly/patternfly-react/issues/1864) -* **DualList:** Hide dropdown when no menu items are provided ([#1909](https://github.com/patternfly/patternfly-react/issues/1909)) ([8ed397e](https://github.com/patternfly/patternfly-react/commit/8ed397e)) - +- **charts:** defaultProps deprecation warning ([#11019](https://github.com/patternfly/patternfly-react/issues/11019)) ([#11027](https://github.com/patternfly/patternfly-react/issues/11027)) ([fc44673](https://github.com/patternfly/patternfly-react/commit/fc44673efe193d37e400b4e87c0f300a205eefbc)) +# [8.0.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.8...@patternfly/react-charts@8.0.0-prerelease.9) (2024-09-18) +### Bug Fixes +- **generate tokens:** prefix tokens with a t\_ ([#11002](https://github.com/patternfly/patternfly-react/issues/11002)) ([0dac6b8](https://github.com/patternfly/patternfly-react/commit/0dac6b88b9f560975627c80c6e8ab816d8b78ac9)) -## [3.4.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.4.1...@patternfly/react-charts@3.4.2) (2019-04-30) +# [8.0.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.7...@patternfly/react-charts@8.0.0-prerelease.8) (2024-09-11) **Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.6...@patternfly/react-charts@8.0.0-prerelease.7) (2024-09-11) +### Bug Fixes +- **charts:** victoryCreateContainer breakage (v6) ([#10925](https://github.com/patternfly/patternfly-react/issues/10925)) ([4a815fb](https://github.com/patternfly/patternfly-react/commit/4a815fb80f0c53c53947fcc53002111bfbf02a4d)) - -## 3.4.1 (2019-04-29) - +# [8.0.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.5...@patternfly/react-charts@8.0.0-prerelease.6) (2024-09-10) ### Bug Fixes -* **version:** bump patternfly version to 2.6.5 ([#1874](https://github.com/patternfly/patternfly-react/issues/1874)) ([e3c8d7c](https://github.com/patternfly/patternfly-react/commit/e3c8d7c)) - +- **deps:** update dependency victory-chart to ^37.1.1 ([#10956](https://github.com/patternfly/patternfly-react/issues/10956)) ([ece3987](https://github.com/patternfly/patternfly-react/commit/ece39872f3b7ef6893d3deeedefb64baa60fbd67)) +# [8.0.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.4...@patternfly/react-charts@8.0.0-prerelease.5) (2024-09-10) +### Bug Fixes +- **deps:** update dependency victory-box-plot to ^37.1.1 ([#10954](https://github.com/patternfly/patternfly-react/issues/10954)) ([fa15a66](https://github.com/patternfly/patternfly-react/commit/fa15a66a71f6bac482173bb01ced9b70101530f8)) -# [3.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.3.0...@patternfly/react-charts@3.4.0) (2019-04-25) +# [8.0.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.3...@patternfly/react-charts@8.0.0-prerelease.4) (2024-09-10) +### Bug Fixes -### Features +- **deps:** update dependency victory-area to ^37.1.1 ([#10951](https://github.com/patternfly/patternfly-react/issues/10951)) ([4491d63](https://github.com/patternfly/patternfly-react/commit/4491d630cf58bb7729a66b93bda2f62a6b94e012)) +- **deps:** update dependency victory-bar to ^37.1.1 ([#10953](https://github.com/patternfly/patternfly-react/issues/10953)) ([8564fff](https://github.com/patternfly/patternfly-react/commit/8564fffd3deff057b52aac5d3dbbd0b2cb06ac0e)) -* **build:** incremental build ([#1817](https://github.com/patternfly/patternfly-react/issues/1817)) ([6bd3d7e](https://github.com/patternfly/patternfly-react/commit/6bd3d7e)) +# [8.0.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.2...@patternfly/react-charts@8.0.0-prerelease.3) (2024-09-10) +### Bug Fixes +- **deps:** update dependency victory-axis to ^37.1.1 ([#10952](https://github.com/patternfly/patternfly-react/issues/10952)) ([879e1e8](https://github.com/patternfly/patternfly-react/commit/879e1e88da35382d7475da63c89ecfa061ecf5a9)) +# [8.0.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-prerelease.1...@patternfly/react-charts@8.0.0-prerelease.2) (2024-09-10) +### Bug Fixes -# 3.3.0 (2019-04-24) +- **deps:** update dependency tslib to ^2.7.0 ([#10949](https://github.com/patternfly/patternfly-react/issues/10949)) ([024b3cc](https://github.com/patternfly/patternfly-react/commit/024b3cc4b1afd4ba9f2dc774c0842712d4fbab1a)) +# [8.0.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.39...@patternfly/react-charts@8.0.0-prerelease.1) (2024-09-07) -### Features +**Note:** Version bump only for package @patternfly/react-charts -* **clipboard:** remove textarea from clipboard copy ([#1840](https://github.com/patternfly/patternfly-react/issues/1840)) ([8bb26a2](https://github.com/patternfly/patternfly-react/commit/8bb26a2)) +# [8.0.0-alpha.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.38...@patternfly/react-charts@8.0.0-alpha.39) (2024-08-27) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.37...@patternfly/react-charts@8.0.0-alpha.38) (2024-08-19) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.36...@patternfly/react-charts@8.0.0-alpha.37) (2024-08-08) -# 3.2.0 (2019-04-23) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.35...@patternfly/react-charts@8.0.0-alpha.36) (2024-07-29) -### Features +**Note:** Version bump only for package @patternfly/react-charts -* **card:** adds card is-hoverable modifier prop ([#1812](https://github.com/patternfly/patternfly-react/issues/1812)) ([a398042](https://github.com/patternfly/patternfly-react/commit/a398042)) +# [8.0.0-alpha.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.34...@patternfly/react-charts@8.0.0-alpha.35) (2024-07-29) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.33...@patternfly/react-charts@8.0.0-alpha.34) (2024-07-29) +### Features +- **MenuToggle:** replaced custom styles with text modifier V6 ([#10793](https://github.com/patternfly/patternfly-react/issues/10793)) ([95a204c](https://github.com/patternfly/patternfly-react/commit/95a204c166019a433facfdc77204ccb33ce1726e)) -## 3.1.2 (2019-04-18) +# [8.0.0-alpha.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.32...@patternfly/react-charts@8.0.0-alpha.33) (2024-07-22) **Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.31...@patternfly/react-charts@8.0.0-alpha.32) (2024-07-15) +### Bug Fixes +- **Toolbar:** updated for parity with Core updates ([#10674](https://github.com/patternfly/patternfly-react/issues/10674)) ([d508325](https://github.com/patternfly/patternfly-react/commit/d50832554af01c6beeb3a5a03f2cdfb41daffbf4)) - -## [3.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.1.0...@patternfly/react-charts@3.1.1) (2019-04-16) +# [8.0.0-alpha.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.30...@patternfly/react-charts@8.0.0-alpha.31) (2024-07-03) **Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.29...@patternfly/react-charts@8.0.0-alpha.30) (2024-07-03) +### Bug Fixes +- **Switch:** updated a11y by removing dynamic labeling ([#10646](https://github.com/patternfly/patternfly-react/issues/10646)) ([730ac69](https://github.com/patternfly/patternfly-react/commit/730ac69eb9544d4831b9eb5fac693fc76a5fe06c)) +# [8.0.0-alpha.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.28...@patternfly/react-charts@8.0.0-alpha.29) (2024-07-02) -# [3.1.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.0.2...@patternfly/react-charts@3.1.0) (2019-04-16) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.27...@patternfly/react-charts@8.0.0-alpha.28) (2024-06-26) ### Features -* **mdx:** use mdx for docs ([#1753](https://github.com/patternfly/patternfly-react/issues/1753)) ([a03ecd0](https://github.com/patternfly/patternfly-react/commit/a03ecd0)) - - +- **Banner,Label:** rename cyan/gold to teal/yellow ([#10661](https://github.com/patternfly/patternfly-react/issues/10661)) ([3e76f17](https://github.com/patternfly/patternfly-react/commit/3e76f173f62b0f5e9aef9e43c597ae5b7fffee92)) - - -## [3.0.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@3.0.1...@patternfly/react-charts@3.0.2) (2019-04-15) +# [8.0.0-alpha.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.26...@patternfly/react-charts@8.0.0-alpha.27) (2024-06-25) **Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.25...@patternfly/react-charts@8.0.0-alpha.26) (2024-06-12) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.24...@patternfly/react-charts@8.0.0-alpha.25) (2024-06-11) +**Note:** Version bump only for package @patternfly/react-charts -## 3.0.1 (2019-04-15) - +# [8.0.0-alpha.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.23...@patternfly/react-charts@8.0.0-alpha.24) (2024-06-05) ### Bug Fixes -* Update React with changes from core ([#1703](https://github.com/patternfly/patternfly-react/issues/1703)) ([a219cae](https://github.com/patternfly/patternfly-react/commit/a219cae)), closes [#1680](https://github.com/patternfly/patternfly-react/issues/1680) [#1684](https://github.com/patternfly/patternfly-react/issues/1684) [#1684](https://github.com/patternfly/patternfly-react/issues/1684) - +- **charts:** renamed cyan to teal, gold to yellow ([#10518](https://github.com/patternfly/patternfly-react/issues/10518)) ([d407554](https://github.com/patternfly/patternfly-react/commit/d4075543aa02e6987abacde96011df2d0347e54a)) +# [8.0.0-alpha.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.22...@patternfly/react-charts@8.0.0-alpha.23) (2024-05-31) +**Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.22 (2024-05-23) -# [3.0.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.4.0...@patternfly/react-charts@3.0.0) (2019-04-15) +### Features -### BREAKING CHANGES +- **Toolbar:** updated spacer props to gap ([#10418](https://github.com/patternfly/patternfly-react/issues/10418)) ([29578a2](https://github.com/patternfly/patternfly-react/commit/29578a2f937456c07fb9c2d8f8ae23a1ad0b2b34)) -* Update React with changes from core ([#1703](https://github.com/patternfly/patternfly-react/issues/1703)) ([a219cae](https://github.com/patternfly/patternfly-react/commit/a219cae)), closes [#1680](https://github.com/patternfly/patternfly-react/issues/1680) [#1684](https://github.com/patternfly/patternfly-react/issues/1684) [#1684](https://github.com/patternfly/patternfly-react/issues/1684) +# 8.0.0-alpha.21 (2024-05-21) +### Features +- **misc, TextContent:** update core version & text content updates ([#10378](https://github.com/patternfly/patternfly-react/issues/10378)) ([1f1b93c](https://github.com/patternfly/patternfly-react/commit/1f1b93c9f5f8bfeb686f7344bfc70152d5453df1)) +# [8.0.0-alpha.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.19...@patternfly/react-charts@8.0.0-alpha.20) (2024-04-22) +**Note:** Version bump only for package @patternfly/react-charts +# 7.3.0-prerelease.6 (2024-03-26) -### Features +**Note:** Version bump only for package @patternfly/react-charts -* **gatsby:** Refactor Gatsby ([#1656](https://github.com/patternfly/patternfly-react/issues/1656)) ([bc32a25](https://github.com/patternfly/patternfly-react/commit/bc32a25)) +# 7.3.0-prerelease.5 (2024-03-22) +**Note:** Version bump only for package @patternfly/react-charts -## [2.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.3.0...@patternfly/react-charts@2.3.1) (2019-04-01) +# [7.3.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.3.0-prerelease.3...@patternfly/react-charts@7.3.0-prerelease.4) (2024-03-05) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +# 7.3.0-prerelease.3 (2024-02-28) -* **misc:** small bug fixes ([#1660](https://github.com/patternfly/patternfly-react/issues/1660)) ([14e4cd3](https://github.com/patternfly/patternfly-react/commit/14e4cd3)) +**Note:** Version bump only for package @patternfly/react-charts +# 7.3.0-prerelease.2 (2024-02-28) +**Note:** Version bump only for package @patternfly/react-charts +# 7.3.0-prerelease.1 (2024-02-14) +### Bug Fixes -# 2.3.0 (2019-03-29) +- **charts:** adjust for Victory types changes ([#10082](https://github.com/patternfly/patternfly-react/issues/10082)) ([714eaca](https://github.com/patternfly/patternfly-react/commit/714eaca02f99f709a6aadc1d9dd58d25940f7403)) +# 7.3.0-prerelease.0 (2024-02-02) -### Features +# 5.2.0 (2024-02-02) -* **Icons:** Paper plane alt icon ([#1643](https://github.com/patternfly/patternfly-react/issues/1643)) ([cd149e0](https://github.com/patternfly/patternfly-react/commit/cd149e0)) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0 (2024-02-02) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.10 (2024-01-15) +**Note:** Version bump only for package @patternfly/react-charts -## 2.2.2 (2019-03-21) +# 7.2.0-prerelease.9 (2024-01-11) **Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.8 (2023-12-11) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.7 (2023-11-10) +**Note:** Version bump only for package @patternfly/react-charts -## [2.2.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.2.0...@patternfly/react-charts@2.2.1) (2019-03-18) +# 7.2.0-prerelease.6 (2023-11-03) **Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.19 (2024-04-02) +**Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.18 (2024-03-27) +**Note:** Version bump only for package @patternfly/react-charts -# [2.2.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.12...@patternfly/react-charts@2.2.0) (2019-03-18) +# [8.0.0-alpha.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.16...@patternfly/react-charts@8.0.0-alpha.17) (2024-03-22) +**Note:** Version bump only for package @patternfly/react-charts -### Features +# 8.0.0-alpha.16 (2024-03-18) -* **core:** clean tsconfigs, add defaultProps to TS-docs ([#1570](https://github.com/patternfly/patternfly-react/issues/1570)) ([9df0f15](https://github.com/patternfly/patternfly-react/commit/9df0f15)) +**Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.15 (2024-03-08) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.13...@patternfly/react-charts@8.0.0-alpha.14) (2024-02-21) +**Note:** Version bump only for package @patternfly/react-charts -## [2.1.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.11...@patternfly/react-charts@2.1.12) (2019-03-15) +# 8.0.0-alpha.13 (2024-02-21) **Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.12 (2024-02-16) +**Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.11 (2024-01-31) +**Note:** Version bump only for package @patternfly/react-charts -## [2.1.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.10...@patternfly/react-charts@2.1.11) (2019-03-15) +# [8.0.0-alpha.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.9...@patternfly/react-charts@8.0.0-alpha.10) (2024-01-26) **Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.9 (2024-01-22) +**Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.8 (2024-01-18) +**Note:** Version bump only for package @patternfly/react-charts -## 2.1.10 (2019-03-14) +# 8.0.0-alpha.7 (2024-01-16) **Note:** Version bump only for package @patternfly/react-charts +# 8.0.0-alpha.6 (2024-01-04) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.4...@patternfly/react-charts@8.0.0-alpha.5) (2023-12-20) +**Note:** Version bump only for package @patternfly/react-charts -## 2.1.9 (2019-03-13) +# 8.0.0-alpha.4 (2023-12-13) **Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.2...@patternfly/react-charts@8.0.0-alpha.3) (2023-12-04) +**Note:** Version bump only for package @patternfly/react-charts +# [8.0.0-alpha.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@8.0.0-alpha.1...@patternfly/react-charts@8.0.0-alpha.2) (2023-11-16) +### Reverts -## 2.1.8 (2019-03-11) +- Revert "Merge remote-tracking branch 'upstream/main' into v6" (#9791) ([b7e8065](https://github.com/patternfly/patternfly-react/commit/b7e80650d3e4cad7a657f6e5a3177485ca4f8c26)), closes [#9791](https://github.com/patternfly/patternfly-react/issues/9791) +# 8.0.0-alpha.1 (2023-09-29) ### Bug Fixes -* **tsconfig:** avatar tsx change ([#1535](https://github.com/patternfly/patternfly-react/issues/1535)) ([8107f5c](https://github.com/patternfly/patternfly-react/commit/8107f5c)) - +- Release alphas from v6 and rebase from main ([#9692](https://github.com/patternfly/patternfly-react/issues/9692)) ([bb022ff](https://github.com/patternfly/patternfly-react/commit/bb022ffc65da8e8c5b5c984412f936cea9424676)), closes [#9651](https://github.com/patternfly/patternfly-react/issues/9651) [#9627](https://github.com/patternfly/patternfly-react/issues/9627) [#9555](https://github.com/patternfly/patternfly-react/issues/9555) [#9543](https://github.com/patternfly/patternfly-react/issues/9543) [#9578](https://github.com/patternfly/patternfly-react/issues/9578) [#9519](https://github.com/patternfly/patternfly-react/issues/9519) [#9603](https://github.com/patternfly/patternfly-react/issues/9603) [#9655](https://github.com/patternfly/patternfly-react/issues/9655) [#9614](https://github.com/patternfly/patternfly-react/issues/9614) [#9606](https://github.com/patternfly/patternfly-react/issues/9606) [#9628](https://github.com/patternfly/patternfly-react/issues/9628) [#9635](https://github.com/patternfly/patternfly-react/issues/9635) [#9649](https://github.com/patternfly/patternfly-react/issues/9649) [#9642](https://github.com/patternfly/patternfly-react/issues/9642) [#9633](https://github.com/patternfly/patternfly-react/issues/9633) [#9637](https://github.com/patternfly/patternfly-react/issues/9637) [#9584](https://github.com/patternfly/patternfly-react/issues/9584) [#9284](https://github.com/patternfly/patternfly-react/issues/9284) +## [7.1.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.1.1-prerelease.8...@patternfly/react-charts@7.1.1-prerelease.9) (2023-09-22) +### Features +- **charts:** add RTL legend support ([#9570](https://github.com/patternfly/patternfly-react/issues/9570)) ([99d8d97](https://github.com/patternfly/patternfly-react/commit/99d8d975eeb2d562357cdcaa37502748d5794564)) -## [2.1.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.6...@patternfly/react-charts@2.1.7) (2019-03-08) +## 7.1.1-prerelease.8 (2023-09-21) **Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.7 (2023-11-10) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.6 (2023-11-03) +**Note:** Version bump only for package @patternfly/react-charts -## 2.1.6 (2019-03-08) +# 7.2.0-prerelease.8 (2023-12-11) **Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.7 (2023-11-10) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.6 (2023-11-03) +**Note:** Version bump only for package @patternfly/react-charts -## [2.1.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.4...@patternfly/react-charts@2.1.5) (2019-03-05) +# 7.2.0-prerelease.10 (2024-01-15) **Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.9 (2024-01-11) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.8 (2023-12-11) +**Note:** Version bump only for package @patternfly/react-charts -## 2.1.4 (2019-03-04) +# 7.2.0-prerelease.7 (2023-11-10) **Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.6 (2023-11-03) +**Note:** Version bump only for package @patternfly/react-charts +# 7.3.0-prerelease.3 (2024-02-28) +**Note:** Version bump only for package @patternfly/react-charts -## [2.1.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.2...@patternfly/react-charts@2.1.3) (2019-02-26) +# 7.3.0-prerelease.2 (2024-02-28) **Note:** Version bump only for package @patternfly/react-charts +# 7.3.0-prerelease.1 (2024-02-14) +### Bug Fixes +- **charts:** adjust for Victory types changes ([#10082](https://github.com/patternfly/patternfly-react/issues/10082)) ([714eaca](https://github.com/patternfly/patternfly-react/commit/714eaca02f99f709a6aadc1d9dd58d25940f7403)) +# 7.3.0-prerelease.0 (2024-02-02) -## [2.1.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.1...@patternfly/react-charts@2.1.2) (2019-02-25) +# 5.2.0 (2024-02-02) **Note:** Version bump only for package @patternfly/react-charts +# 7.2.0 (2024-02-02) +**Note:** Version bump only for package @patternfly/react-charts - - -## [2.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.1.0...@patternfly/react-charts@2.1.1) (2019-02-25) +# 7.2.0-prerelease.10 (2024-01-15) **Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.9 (2024-01-11) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.8 (2023-12-11) +**Note:** Version bump only for package @patternfly/react-charts -# 2.1.0 (2019-02-25) - +# 7.2.0-prerelease.7 (2023-11-10) -### Features +**Note:** Version bump only for package @patternfly/react-charts -* **charts:** Add ChartAxis ([#1309](https://github.com/patternfly/patternfly-react/issues/1309)) ([cd6788b](https://github.com/patternfly/patternfly-react/commit/cd6788b)) +# 7.2.0-prerelease.6 (2023-11-03) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.5 (2023-10-26) +**Note:** Version bump only for package @patternfly/react-charts +# 7.2.0-prerelease.4 (2023-10-10) -## [2.0.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.0.4...@patternfly/react-charts@2.0.5) (2019-02-20) +**Note:** Version bump only for package @patternfly/react-charts +# [7.2.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.2.0-prerelease.2...@patternfly/react-charts@7.2.0-prerelease.3) (2023-10-10) -### Bug Fixes +**Note:** Version bump only for package @patternfly/react-charts -* **lint:** fix linting glob and auto-fixable linter errors ([#1256](https://github.com/patternfly/patternfly-react/issues/1256)) ([#1409](https://github.com/patternfly/patternfly-react/issues/1409)) ([0b637fe](https://github.com/patternfly/patternfly-react/commit/0b637fe)) +# 7.2.0-prerelease.2 (2023-10-09) +**Note:** Version bump only for package @patternfly/react-charts +# [7.2.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.2.0-prerelease.0...@patternfly/react-charts@7.2.0-prerelease.1) (2023-10-09) +### Bug Fixes +- **charts:** legendAllowWrap function generates an null error ([#9719](https://github.com/patternfly/patternfly-react/issues/9719)) ([5b4cbf4](https://github.com/patternfly/patternfly-react/commit/5b4cbf41bf11785ffe66dc263c7c26e61d25cacd)) -## [2.0.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.0.3...@patternfly/react-charts@2.0.4) (2019-02-19) +# [7.2.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.1.1...@patternfly/react-charts@7.2.0-prerelease.0) (2023-10-05) **Note:** Version bump only for package @patternfly/react-charts - - - - -## [2.0.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.0.2...@patternfly/react-charts@2.0.3) (2019-02-15) +## [7.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.1.1-prerelease.10...@patternfly/react-charts@7.1.1) (2023-10-05) **Note:** Version bump only for package @patternfly/react-charts +## 7.1.1-prerelease.10 (2023-10-03) +### Bug Fixes +- whitespace changes to trigger prereleases ([#9702](https://github.com/patternfly/patternfly-react/issues/9702)) ([741c248](https://github.com/patternfly/patternfly-react/commit/741c24825b503e116c77cf304aa3e4e3a9ff7841)) +## [7.1.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.1.1-prerelease.8...@patternfly/react-charts@7.1.1-prerelease.9) (2023-09-22) -## [2.0.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.0.1...@patternfly/react-charts@2.0.2) (2019-02-13) +### Features -**Note:** Version bump only for package @patternfly/react-charts +- **charts:** add RTL legend support ([#9570](https://github.com/patternfly/patternfly-react/issues/9570)) ([99d8d97](https://github.com/patternfly/patternfly-react/commit/99d8d975eeb2d562357cdcaa37502748d5794564)) +## 7.1.1-prerelease.8 (2023-09-21) +**Note:** Version bump only for package @patternfly/react-charts +## [7.1.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.1.1-prerelease.6...@patternfly/react-charts@7.1.1-prerelease.7) (2023-09-18) +**Note:** Version bump only for package @patternfly/react-charts -## [2.0.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@2.0.0...@patternfly/react-charts@2.0.1) (2019-02-12) +## 7.1.1-prerelease.6 (2023-09-13) **Note:** Version bump only for package @patternfly/react-charts +## [7.1.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.1.1-prerelease.4...@patternfly/react-charts@7.1.1-prerelease.5) (2023-09-07) +**Note:** Version bump only for package @patternfly/react-charts +## [7.1.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.1.1-prerelease.3...@patternfly/react-charts@7.1.1-prerelease.4) (2023-09-06) +**Note:** Version bump only for package @patternfly/react-charts -# [2.0.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.4.3...@patternfly/react-charts@2.0.0) (2019-02-08) - +## 7.1.1-prerelease.3 (2023-09-05) -### Code Refactoring +**Note:** Version bump only for package @patternfly/react-charts -* **AboutModal:** Upgrade core to 1.0.175 and Refactor AboutModal ([#1307](https://github.com/patternfly/patternfly-react/issues/1307)) ([1f85756](https://github.com/patternfly/patternfly-react/commit/1f85756)), closes [#1267](https://github.com/patternfly/patternfly-react/issues/1267) +## 7.1.1-prerelease.2 (2023-08-31) +**Note:** Version bump only for package @patternfly/react-charts -### BREAKING CHANGES +## 7.1.1-prerelease.1 (2023-08-29) -* **AboutModal:** removed heroImg and heroImageSrc and heroImageAlt props +### Bug Fixes +- **Charts, Table:** Fixed lit erros in chasrt and table ([#9507](https://github.com/patternfly/patternfly-react/issues/9507)) ([f68e4ba](https://github.com/patternfly/patternfly-react/commit/f68e4ba2ca557be928940a7297819b9b9037c41d)) +- **ChartScatter:** consider bubbleProperty if it is set ([#9282](https://github.com/patternfly/patternfly-react/issues/9282)) ([6020af4](https://github.com/patternfly/patternfly-react/commit/6020af4a90dfecff42d4de9ee71650fb9db4c45a)), closes [/github.com/FormidableLabs/victory/blob/bbc1e2a39448d7fb6724f916afacf5f6eab7d1b3/packages/victory-scatter/src/helper-methods.tsx#L35-L43](https://github.com//github.com/FormidableLabs/victory/blob/bbc1e2a39448d7fb6724f916afacf5f6eab7d1b3/packages/victory-scatter/src/helper-methods.tsx/issues/L35-L43) +# 5.0.0 (2023-07-27) +# [7.1.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0...@patternfly/react-charts@7.1.0-prerelease.0) (2023-07-27) +**Note:** Version bump only for package @patternfly/react-charts -## [1.4.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.4.2...@patternfly/react-charts@1.4.3) (2019-02-01) +# 7.0.0 (2023-07-27) **Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-prerelease.12 (2023-07-20) +**Note:** Version bump only for package @patternfly/react-charts +# [7.0.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-prerelease.10...@patternfly/react-charts@7.0.0-prerelease.11) (2023-07-14) +**Note:** Version bump only for package @patternfly/react-charts -## [1.4.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.4.1...@patternfly/react-charts@1.4.2) (2019-01-29) +# 7.0.0-prerelease.10 (2023-07-13) **Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-prerelease.9 (2023-07-06) +### Bug Fixes +- **charts:** export getThemeColors ([#9338](https://github.com/patternfly/patternfly-react/issues/9338)) ([4d1f72d](https://github.com/patternfly/patternfly-react/commit/4d1f72d7668b75b3381953f615af075daf40b420)) +# 7.0.0-prerelease.8 (2023-07-06) -## [1.4.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.4.0...@patternfly/react-charts@1.4.1) (2019-01-21) +**Note:** Version bump only for package @patternfly/react-charts +# [7.0.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-prerelease.6...@patternfly/react-charts@7.0.0-prerelease.7) (2023-06-30) ### Bug Fixes -* **readme:** update readme for react-charts ([#1225](https://github.com/patternfly/patternfly-react/issues/1225)) ([7799263](https://github.com/patternfly/patternfly-react/commit/7799263)) +- **charts:** Update chart legend tooltip spacing ([#9323](https://github.com/patternfly/patternfly-react/issues/9323)) ([77e260c](https://github.com/patternfly/patternfly-react/commit/77e260c8d51b0765dea1dadbcef691bd7a51ef20)) +# 7.0.0-prerelease.6 (2023-06-21) +**Note:** Version bump only for package @patternfly/react-charts - - -# [1.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.3.0...@patternfly/react-charts@1.4.0) (2019-01-17) - +# [7.0.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-prerelease.4...@patternfly/react-charts@7.0.0-prerelease.5) (2023-06-15) ### Features -* **Alert:** Add optional Close button to Alert via onClose prop ([#1200](https://github.com/patternfly/patternfly-react/issues/1200)) ([9d59dcb](https://github.com/patternfly/patternfly-react/commit/9d59dcb)), closes [#1036](https://github.com/patternfly/patternfly-react/issues/1036) +- **charts:** Update Victory packages to latest version ([#9276](https://github.com/patternfly/patternfly-react/issues/9276)) ([515b36f](https://github.com/patternfly/patternfly-react/commit/515b36fd4f3b1f82c6daf7625ecf0189c7f0470d)) +# [7.0.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-prerelease.3...@patternfly/react-charts@7.0.0-prerelease.4) (2023-06-15) +### Bug Fixes +- **release:** ensure component package.json file has correct data ([#9272](https://github.com/patternfly/patternfly-react/issues/9272)) ([6053a6f](https://github.com/patternfly/patternfly-react/commit/6053a6f9acc0b1a9856423db59523558c5abd629)) +# 7.0.0-prerelease.3 (2023-06-13) -# [1.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.7...@patternfly/react-charts@1.3.0) (2019-01-16) +### Bug Fixes +- **docs:** update use of deprecated tag and clean up changelogs ([#9259](https://github.com/patternfly/patternfly-react/issues/9259)) ([8de83dc](https://github.com/patternfly/patternfly-react/commit/8de83dc3b2fb88094fd3c21bda2ed6e371986cba)) -### Features +# [7.0.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-prerelease.1...@patternfly/react-charts@7.0.0-prerelease.2) (2023-06-06) -* **Table:** introduce new component Table based on pf4 designs ([#821](https://github.com/patternfly/patternfly-react/issues/821)) ([7b38cbc](https://github.com/patternfly/patternfly-react/commit/7b38cbc)) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-prerelease.1 (2023-06-06) +### Bug Fixes +- **release:** dryrun publishing prereleases ([#9242](https://github.com/patternfly/patternfly-react/issues/9242)) ([e4c35f1](https://github.com/patternfly/patternfly-react/commit/e4c35f14cd57be132179e51ae2bb223600a35f0e)) +# [7.0.0-alpha.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.34...@patternfly/react-charts@7.0.0-alpha.35) (2023-06-02) - -## [1.2.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.6...@patternfly/react-charts@1.2.7) (2019-01-11) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.34 (2023-06-01) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.33 (2023-05-31) **Note:** Version bump only for package @patternfly/react-charts - -## [1.2.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.5...@patternfly/react-charts@1.2.6) (2019-01-10) +# 7.0.0-alpha.32 (2023-05-23) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +# [7.0.0-alpha.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.30...@patternfly/react-charts@7.0.0-alpha.31) (2023-05-19) -* **prerelease:** attempt to add prerelease channel to react-charts ([#1160](https://github.com/patternfly/patternfly-react/issues/1160)) ([0e3e807](https://github.com/patternfly/patternfly-react/commit/0e3e807)) +**Note:** Version bump only for package @patternfly/react-charts +# [7.0.0-alpha.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.29...@patternfly/react-charts@7.0.0-alpha.30) (2023-05-18) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.29 (2023-05-18) - -## [1.2.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.4...@patternfly/react-charts@1.2.5) (2019-01-10) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.28 (2023-05-18) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.27 (2023-05-18) **Note:** Version bump only for package @patternfly/react-charts - -## [1.2.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.3...@patternfly/react-charts@1.2.4) (2018-12-20) +# 7.0.0-alpha.26 (2023-05-17) +### Bug Fixes +- **beta:** promote components + features out of beta for v5 ([#8912](https://github.com/patternfly/patternfly-react/issues/8912)) ([34c1688](https://github.com/patternfly/patternfly-react/commit/34c16885539531434832205544f96d3ffddabb79)) +# 7.0.0-alpha.25 (2023-05-16) **Note:** Version bump only for package @patternfly/react-charts - -## [1.2.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.2...@patternfly/react-charts@1.2.3) (2018-12-19) - - - +# 7.0.0-alpha.24 (2023-05-08) **Note:** Version bump only for package @patternfly/react-charts - -## [1.2.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.1...@patternfly/react-charts@1.2.2) (2018-12-07) +# [7.0.0-alpha.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.22...@patternfly/react-charts@7.0.0-alpha.23) (2023-05-05) +### Bug Fixes +- **deps:** updated Core for v5 versioning ([#9075](https://github.com/patternfly/patternfly-react/issues/9075)) ([3879fc7](https://github.com/patternfly/patternfly-react/commit/3879fc757aefeed80b0694365aa20d5ca856a797)) +# 7.0.0-alpha.22 (2023-05-05) **Note:** Version bump only for package @patternfly/react-charts - -## [1.2.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.2.0...@patternfly/react-charts@1.2.1) (2018-11-28) +# 7.0.0-alpha.21 (2023-05-03) +### Features +- **charts:** Victory package update ([#9021](https://github.com/patternfly/patternfly-react/issues/9021)) ([805fb87](https://github.com/patternfly/patternfly-react/commit/805fb87698f427f66d167d303f87c033ac7c6c25)) +# 7.0.0-alpha.20 (2023-04-25) **Note:** Version bump only for package @patternfly/react-charts - -# [1.2.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.1.0...@patternfly/react-charts@1.2.0) (2018-11-27) - +# 7.0.0-alpha.19 (2023-04-13) -### Features +### Bug Fixes -* **Popover:** Add PF4 Popover ([#754](https://github.com/patternfly/patternfly-react/issues/754)) ([17cf0c0](https://github.com/patternfly/patternfly-react/commit/17cf0c0)) +- general clean up ([#8944](https://github.com/patternfly/patternfly-react/issues/8944)) ([7a6ea59](https://github.com/patternfly/patternfly-react/commit/7a6ea59c7b029cd5ffe22117fa81706c28feadfe)) +# 7.0.0-alpha.18 (2023-04-13) +### Features +- **infrastructure:** Added ability import components directly to support fed modules tree-shaking of shared packages. ([#8832](https://github.com/patternfly/patternfly-react/issues/8832)) ([16c15bf](https://github.com/patternfly/patternfly-react/commit/16c15bf09c1df7cc581336a7a3047dc8b11f8be0)) - -# [1.1.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.0.5...@patternfly/react-charts@1.1.0) (2018-11-20) +# 7.0.0-alpha.17 (2023-04-12) +**Note:** Version bump only for package @patternfly/react-charts -### Features +# 7.0.0-alpha.16 (2023-04-05) -* **PF4 Page:** Allow passing of custom ref for condensed header ([#941](https://github.com/patternfly/patternfly-react/issues/941)) ([889ec1a](https://github.com/patternfly/patternfly-react/commit/889ec1a)) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.15 (2023-04-05) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.14 (2023-04-03) - -## [1.0.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.0.4...@patternfly/react-charts@1.0.5) (2018-11-16) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.13 (2023-03-27) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.12 (2023-03-18) **Note:** Version bump only for package @patternfly/react-charts - -## [1.0.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.0.3...@patternfly/react-charts@1.0.4) (2018-11-14) - +# 7.0.0-alpha.11 (2023-03-17) +**Note:** Version bump only for package @patternfly/react-charts +# [7.0.0-alpha.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.9...@patternfly/react-charts@7.0.0-alpha.10) (2023-03-02) **Note:** Version bump only for package @patternfly/react-charts - -## [1.0.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.0.2...@patternfly/react-charts@1.0.3) (2018-11-12) +# 7.0.0-alpha.9 (2023-03-01) +**Note:** Version bump only for package @patternfly/react-charts -### Bug Fixes +# 7.0.0-alpha.8 (2023-02-27) -* **charts:** address typescript issues ([#902](https://github.com/patternfly/patternfly-react/issues/902)) ([83cb283](https://github.com/patternfly/patternfly-react/commit/83cb283)) +**Note:** Version bump only for package @patternfly/react-charts +# [7.0.0-alpha.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.6...@patternfly/react-charts@7.0.0-alpha.7) (2023-02-15) +**Note:** Version bump only for package @patternfly/react-charts +# 7.0.0-alpha.6 (2023-02-10) - -## [1.0.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@1.0.1...@patternfly/react-charts@1.0.2) (2018-11-07) +### Bug Fixes +- **charts:** fix broken tooltip examples due to Tooltip outputting a new div tag in the SVG ([#8592](https://github.com/patternfly/patternfly-react/issues/8592)) ([a7d2e12](https://github.com/patternfly/patternfly-react/commit/a7d2e12769c1208eedb88e5574d7ae7dd34e434c)) +# [7.0.0-alpha.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.4...@patternfly/react-charts@7.0.0-alpha.5) (2023-02-09) +### Features -**Note:** Version bump only for package @patternfly/react-charts +- **charts:** remove deprecated theme variant code ([#8590](https://github.com/patternfly/patternfly-react/issues/8590)) ([12e1c47](https://github.com/patternfly/patternfly-react/commit/12e1c472f1260d161f178e170782de8a7fc63b80)) - -## 1.0.1 (2018-11-07) +# [7.0.0-alpha.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-charts@7.0.0-alpha.3...@patternfly/react-charts@7.0.0-alpha.4) (2023-02-08) +### Features +- **charts:** update Victory dependencies for v5 ([#8606](https://github.com/patternfly/patternfly-react/issues/8606)) ([19a5e93](https://github.com/patternfly/patternfly-react/commit/19a5e939c417a4ad31b4e2a5fae24b1d7698a025)) +# 7.0.0-alpha.3 (2023-02-08) **Note:** Version bump only for package @patternfly/react-charts - -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/react-charts/README.md b/packages/react-charts/README.md index ae3e0afe2fb..eb38bc5fd29 100644 --- a/packages/react-charts/README.md +++ b/packages/react-charts/README.md @@ -1,34 +1,25 @@ # @patternfly/react-charts -This package provides PatternFly charting components for [PatternFly 4][patternfly-4]. - -### Prerequisite - -#### Node Environment - -This project currently supports Node [Active LTS](https://github.com/nodejs/Release#release-schedule) releases. Please stay current with Node Active LTS when developing patternfly-react. - -For example, to develop with Node 8, use the following: - -``` -nvm install 8 -nvm use 8 -``` - -This project also requires a Yarn version of >=1.6.0. The latest version can be installed [here](https://yarnpkg.com/). +This package provides PatternFly charting components for [PatternFly][patternfly]. ### Installing -``` +```sh yarn add @patternfly/react-charts +yarn add victory ``` or -``` +```sh npm install @patternfly/react-charts --save +npm install victory --save ``` +Note that Victory is now an optional peer dependency, allowing future chart libraries to be installed without including Victory dependencies and vice versa + - You may choose to install the single "victory" package to cover all features + - Or, install packages based on the features used in your app (e.g., "victory-core", "victory-tooltip", etc.). + # Usage #### Pre-requisites @@ -42,7 +33,7 @@ import '@patternfly/react-core/dist/styles/base.css'; #### Example Component Usage ```js -import { Area } from '@patternfly/react-charts'; +import { Area } from '@patternfly/react-charts/victory'; export default ; @@ -60,28 +51,12 @@ You can also find how each component is meant to be used from a design perspecti Note: All commands below assume you are on the root directory in this repository. -### Install - -Run to install all the dependencies - -```sh -yarn && yarn bootstrap && yarn build && yarn build:docs -``` - -### Running - -To start the site locally. - -```sh -yarn build && yarn start:pf4 -``` - -### Building +### Install & run locally -To build the site. +Run to install all the dependencies, build and run the site locally. ```sh -yarn build:docs +yarn install && yarn start ``` # Contributing Components @@ -105,4 +80,4 @@ yarn test packages/react-charts ``` [patternfly-4]: https://github.com/patternfly/patternfly -[docs]: https://patternfly-react.surge.sh/ +[docs]: https://react-staging.patternfly.org/ diff --git a/packages/react-charts/package.json b/packages/react-charts/package.json index 2bcd0c4e225..c5985f66b84 100644 --- a/packages/react-charts/package.json +++ b/packages/react-charts/package.json @@ -1,10 +1,20 @@ { "name": "@patternfly/react-charts", - "version": "6.41.0", + "version": "8.6.0-prerelease.1", "description": "This library provides a set of React chart components for use with the PatternFly reference implementation.", "main": "dist/js/index.js", "module": "dist/esm/index.js", "types": "dist/esm/index.d.ts", + "typesVersions": { + "*": { + "echarts": [ + "dist/esm/echarts/index.d.ts" + ], + "victory": [ + "dist/esm/victory/index.d.ts" + ] + } + }, "patternfly:src": "src/", "sideEffects": [ "*.css", @@ -12,7 +22,7 @@ ], "publishConfig": { "access": "public", - "tag": "prerelease" + "tag": "prerelase" }, "repository": { "type": "git", @@ -29,40 +39,98 @@ }, "homepage": "https://github.com/patternfly/patternfly-react#readme", "dependencies": { - "@patternfly/react-styles": "^4.38.0", - "@patternfly/react-tokens": "^4.40.0", - "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.19", - "tslib": "^2.0.0", - "victory-area": "^35.9.0", - "victory-axis": "^35.9.0", - "victory-bar": "^35.9.0", - "victory-chart": "^35.9.0", - "victory-core": "^35.9.0", - "victory-create-container": "^35.9.1", - "victory-group": "^35.9.0", - "victory-legend": "^35.9.0", - "victory-line": "^35.9.0", - "victory-pie": "^35.9.0", - "victory-scatter": "^35.9.0", - "victory-stack": "^35.9.0", - "victory-tooltip": "^35.9.1", - "victory-voronoi-container": "^35.9.1", - "victory-zoom-container": "^35.9.0" + "@patternfly/react-styles": "workspace:^", + "@patternfly/react-tokens": "workspace:^", + "hoist-non-react-statics": "^3.3.2", + "lodash": "^4.17.23", + "tslib": "^2.8.1" + }, + "devDependencies": { + "@types/lodash": "^4.17.24", + "fs-extra": "^11.3.3", + "jest-canvas-mock": "^2.5.2" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "echarts": "^5.6.0 || ^6.0.0", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19", + "victory-area": "^37.3.6", + "victory-axis": "^37.3.6", + "victory-bar": "^37.3.6", + "victory-box-plot": "^37.3.6", + "victory-chart": "^37.3.6", + "victory-core": "^37.3.6", + "victory-create-container": "^37.3.6", + "victory-cursor-container": "^37.3.6", + "victory-group": "^37.3.6", + "victory-legend": "^37.3.6", + "victory-line": "^37.3.6", + "victory-pie": "^37.3.6", + "victory-scatter": "^37.3.6", + "victory-stack": "^37.3.6", + "victory-tooltip": "^37.3.6", + "victory-voronoi-container": "^37.3.6", + "victory-zoom-container": "^37.3.6" }, - "scripts": { - "clean": "rimraf dist" + "peerDependenciesMeta": { + "echarts": { + "optional": true + }, + "victory-area": { + "optional": true + }, + "victory-axis": { + "optional": true + }, + "victory-bar": { + "optional": true + }, + "victory-box-plot": { + "optional": true + }, + "victory-chart": { + "optional": true + }, + "victory-core": { + "optional": true + }, + "victory-create-container": { + "optional": true + }, + "victory-cursor-container": { + "optional": true + }, + "victory-group": { + "optional": true + }, + "victory-legend": { + "optional": true + }, + "victory-line": { + "optional": true + }, + "victory-pie": { + "optional": true + }, + "victory-scatter": { + "optional": true + }, + "victory-stack": { + "optional": true + }, + "victory-tooltip": { + "optional": true + }, + "victory-voronoi-container": { + "optional": true + }, + "victory-zoom-container": { + "optional": true + } }, - "devDependencies": { - "@types/lodash": "^4.14.157", - "css": "^2.2.3", - "fs-extra": "^6.0.1", - "glob": "^7.1.2", - "rimraf": "^2.6.2", - "typescript": "^4.0.0" + "scripts": { + "clean": "rimraf dist echarts victory", + "build:single:packages": "node ../../scripts/build-single-packages.mjs --config single-packages.config.json", + "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json" } } diff --git a/packages/react-charts/single-packages.config.json b/packages/react-charts/single-packages.config.json new file mode 100644 index 00000000000..274428abad0 --- /dev/null +++ b/packages/react-charts/single-packages.config.json @@ -0,0 +1,4 @@ +{ + "packageName": "@patternfly/react-charts", + "exclude": ["dist/esm/echarts/deprecated/index.js", "dist/esm/echarts/next/index.js", "dist/esm/victory/deprecated/index.js", "dist/esm/victory/next/index.js"] +} diff --git a/packages/react-charts/src/components/Chart/Chart.tsx b/packages/react-charts/src/components/Chart/Chart.tsx deleted file mode 100644 index 6995f855830..00000000000 --- a/packages/react-charts/src/components/Chart/Chart.tsx +++ /dev/null @@ -1,535 +0,0 @@ -import * as React from 'react'; -import hoistNonReactStatics from 'hoist-non-react-statics'; - -/* eslint-disable camelcase */ -import chart_legend_Margin from '@patternfly/react-tokens/dist/esm/chart_legend_Margin'; - -import { - AnimatePropTypeInterface, - D3Scale, - DomainPropType, - DomainPaddingPropType, - EventCallbackInterface, - EventPropTypeInterface, - PaddingProps, - RangePropType, - ScalePropType, - StringOrNumberOrCallback, - StringOrNumberOrList, - VictoryStyleInterface, - VictoryStyleObject -} from 'victory-core'; -import { AxesType, VictoryChart, VictoryChartProps } from 'victory-chart'; -import { ChartContainer } from '../ChartContainer'; -import { ChartLegend, ChartLegendOrientation, ChartLegendPosition } from '../ChartLegend'; -import { ChartCommonStyles, ChartThemeDefinition } from '../ChartTheme'; -import { getClassName, getComputedLegend, getLabelTextSize, getPaddingForSide, getTheme } from '../ChartUtils'; - -/** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-chart/src/index.d.ts - */ -export interface ChartProps extends VictoryChartProps { - /** - * The animate prop specifies props for VictoryAnimation to use. - * The animate prop should also be used to specify enter and exit - * transition configurations with the `onExit` and `onEnter` namespaces respectively. - * - * @propType boolean | object - * @example {duration: 500, onExit: () => {}, onEnter: {duration: 500, before: () => ({y: 0})})} - */ - animate?: boolean | AnimatePropTypeInterface; - /** - * The ariaDesc prop specifies the description of the chart/SVG to assist with - * accessibility for screen readers. - * - * Note: Overridden by the desc prop of containerComponent - */ - ariaDesc?: string; - /** - * The ariaTitle prop specifies the title to be applied to the SVG to assist - * accessibility for screen readers. - * - * Note: Overridden by the title prop of containerComponent - */ - ariaTitle?: string; - /** - * The backgroundComponent prop takes a component instance which will be responsible for rendering a background if the - * Chart's style component includes background styles. The new element created from the passed backgroundComponent - * will be provided with the following properties calculated by Chart: height, polar, scale, style, x, y, width. - * All of these props on Background should take prececence over what VictoryChart is trying to set. - */ - backgroundComponent?: React.ReactElement; - /** - * The children to render with the chart - */ - children?: React.ReactNode | React.ReactNode[]; - /** - * The containerComponent prop takes an entire component which will be used to - * create a container element for standalone charts. - * The new element created from the passed containerComponent wil be provided with - * these props from ChartArea: height, width, children - * (the chart itself) and style. Props that are not provided by the - * child chart component include title and desc, both of which - * are intended to add accessibility to Victory components. The more descriptive these props - * are, the more accessible your data will be for people using screen readers. - * Any of these props may be overridden by passing in props to the supplied component, - * or modified or ignored within the custom component itself. If a dataComponent is - * not provided, ChartArea will use the default ChartContainer component. - * - * @example - */ - containerComponent?: React.ReactElement; - /** - * Note: This prop should not be set manually. - * - * @hide - */ - defaultAxes?: AxesType; - /** - * Note: This prop should not be set manually. - * - * @hide - */ - defaultPolarAxes?: AxesType; - /** - * The domain prop describes the range of values your chart will include. This prop can be - * given as a array of the minimum and maximum expected values for your chart, - * or as an object that specifies separate arrays for x and y. - * If this prop is not provided, a domain will be calculated from data, or other - * available information. - * - * @propType number[] | { x: number[], y: number[] } - * @example [low, high], { x: [low, high], y: [low, high] } - * - * [-1, 1], {x: [0, 100], y: [0, 1]} - */ - domain?: DomainPropType; - /** - * The domainPadding prop specifies a number of pixels of padding to add to the - * beginning and end of a domain. This prop is useful for explicitly spacing ticks farther - * from the origin to prevent crowding. This prop should be given as an object with - * numbers specified for x and y. - * - * @propType number | number[] | { x: number[], y: number[] } - * @example [left, right], { x: [left, right], y: [bottom, top] } - * - * {x: [10, -10], y: 5} - */ - domainPadding?: DomainPaddingPropType; - /** - * The endAngle props defines the overall end angle of a polar chart in degrees. This prop is used in conjunction with - * startAngle to create polar chart that spans only a segment of a circle, or to change overall rotation of the chart. - * This prop should be given as a number of degrees. Degrees are defined as starting at the 3 o'clock position, and - * proceeding counterclockwise. - */ - endAngle?: number; - /** - * Similar to data accessor props `x` and `y`, this prop may be used to functionally - * assign eventKeys to data - * - * @propType number | string | Function - */ - eventKey?: StringOrNumberOrCallback; - /** - * The event prop takes an array of event objects. Event objects are composed of - * a target, an eventKey, and eventHandlers. Targets may be any valid style namespace - * for a given component, so "data" and "labels" are all valid targets for ChartPie - * events. The eventKey may optionally be used to select a single element by index rather than - * an entire set. The eventHandlers object should be given as an object whose keys are standard - * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given - * as an object or an array of objects with optional target and eventKey keys, - * and a mutation key whose value is a function. The target and eventKey keys - * will default to those corresponding to the element the event handler was attached to. - * The mutation function will be called with the calculated props for the individual selected - * element (i.e. a single bar), and the object returned from the mutation function - * will override the props of the selected element via object assignment. - * - * @propType object[] - * @example - * events={[ - * { - * target: "data", - * eventKey: 1, - * eventHandlers: { - * onClick: () => { - * return [ - * { - * eventKey: 2, - * mutation: (props) => { - * return {style: merge({}, props.style, {fill: "orange"})}; - * } - * }, { - * eventKey: 2, - * target: "labels", - * mutation: () => { - * return {text: "hey"}; - * } - * } - * ]; - * } - * } - * } - * ]} - */ - events?: EventPropTypeInterface[]; - /** - * Chart uses the standard externalEventMutations prop. - * - * @propType object[] - */ - externalEventMutations?: EventCallbackInterface[]; - /** - * The groupComponent prop takes an entire component which will be used to - * create group elements for use within container elements. This prop defaults - * to a tag on web, and a react-native-svg tag on mobile - */ - groupComponent?: React.ReactElement; - /** - * Specifies the height the svg viewBox of the chart container. This value should be given as a - * number of pixels. - * - * Because Victory renders responsive containers, the width and height props do not determine the width and - * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of - * pixels will depend on the size of the container the chart is rendered into. Typically, the parent container is set - * to the same width in order to maintain the aspect ratio. - */ - height?: number; - /** - * The horizontal prop determines whether data will be plotted horizontally. When this prop is set to true, the - * independent variable will be plotted on the y axis and the dependent variable will be plotted on the x axis. - */ - horizontal?: boolean; - /** - * When the innerRadius prop is set, polar charts will be hollow rather than circular. - * - * @propType number | Function - */ - innerRadius?: number; - /** - * Allows legend items to wrap. A value of true allows the legend to wrap onto the next line - * if its container is not wide enough. - * - * Note: This is overridden by the legendItemsPerRow property - */ - legendAllowWrap?: boolean; - /** - * The legend component to render with chart. - * - * Note: Use legendData so the legend width can be calculated and positioned properly. - * Default legend properties may be applied - */ - legendComponent?: React.ReactElement; - /** - * Specify data via the data prop. ChartLegend expects data as an - * array of objects with name (required), symbol, and labels properties. - * The data prop must be given as an array. - * - * @example legendData={[{ name: `GBps capacity - 45%` }, { name: 'Unused' }]} - */ - legendData?: { - name?: string; - symbol?: { - fill?: string; - type?: string; - }; - }[]; - /** - * The orientation prop takes a string that defines whether legend data - * are displayed in a row or column. When orientation is "horizontal", - * legend items will be displayed in a single row. When orientation is - * "vertical", legend items will be displayed in a single column. Line - * and text-wrapping is not currently supported, so "vertical" - * orientation is both the default setting and recommended for - * displaying many series of data. - */ - legendOrientation?: 'horizontal' | 'vertical'; - /** - * The legend position relation to the chart. Valid values are 'bottom', 'bottom-left', and 'right' - * - * Note: When adding a legend, padding may need to be adjusted in order to accommodate the extra legend. In some - * cases, the legend may not be visible until enough padding is applied. - */ - legendPosition?: 'bottom' | 'bottom-left' | 'right'; - /** - * The maxDomain prop defines a maximum domain value for a chart. This prop is useful in situations where the maximum - * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain - * prop is set in addition to maximumDomain, domain will be used. - * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the - * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to - * the y axis. - * - * @example - * - * maxDomain={0} - * maxDomain={{ y: 0 }} - */ - maxDomain?: number | { x?: number; y?: number }; - /** - * The minDomain prop defines a minimum domain value for a chart. This prop is useful in situations where the minimum - * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain - * prop is set in addition to minimumDomain, domain will be used. - * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the - * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to - * the y axis. - * - * @example - * - * minDomain={0} - * minDomain={{ y: 0 }} - */ - minDomain?: number | { x?: number; y?: number }; - /** - * The padding props specifies the amount of padding in number of pixels between - * the edge of the chart and any rendered child components. This prop can be given - * as a number or as an object with padding specified for top, bottom, left - * and right. - * - * @propType number | { top: number, bottom: number, left: number, right: number } - */ - padding?: PaddingProps; - /** - * Note: This prop should not be set manually. - * - * @hide - */ - prependDefaultAxes?: boolean; - /** - * Victory components can pass a boolean polar prop to specify whether a label is part of a polar chart. - */ - polar?: boolean; - /** - * The range prop describes the dimensions over which data may be plotted. For cartesian coordinate systems, this - * corresponds to minimum and maximum svg coordinates in the x and y dimension. In polar coordinate systems this - * corresponds to a range of angles and radii. When this value is not given it will be calculated from the width, - * height, and padding, or from the startAngle and endAngle in the case of polar charts. All components in a given - * chart must share the same range, so setting this prop on children nested within Chart, ChartStack, or - * ChartGroup will have no effect. This prop is usually not set manually. - * - * @propType number[] | { x: number[], y: number[] } - * @example [low, high] | { x: [low, high], y: [low, high] } - * - * Cartesian: range={{ x: [50, 250], y: [50, 250] }} - * Polar: range={{ x: [0, 360], y: [0, 250] }} - */ - range?: RangePropType; - /** - * The scale prop determines which scales your chart should use. This prop can be - * given as a string specifying a supported scale ("linear", "time", "log", "sqrt"), - * as a d3 scale function, or as an object with scales specified for x and y - * - * @propType string | { x: string, y: string } - * @example d3Scale.time(), {x: "linear", y: "log"} - */ - scale?: - | ScalePropType - | D3Scale - | { - x?: ScalePropType | D3Scale; - y?: ScalePropType | D3Scale; - }; - /** - * The sharedEvents prop is used internally to coordinate events between components. - * - * Note: This prop should not be set manually. - * - * @hide - */ - sharedEvents?: { events: any[]; getEventState: Function }; - /** - * Convenience prop to hide both x and y axis, which are shown by default. Alternatively, the axis can be hidden via - * chart styles. - */ - showAxis?: boolean; - /** - * By default domainPadding is coerced to existing quadrants. This means that if a given domain only includes positive - * values, no amount of padding applied by domainPadding will result in a domain with negative values. This is the - * desired behavior in most cases. For users that need to apply padding without regard to quadrant, the - * singleQuadrantDomainPadding prop may be used. This prop may be given as a boolean or an object with boolean values - * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied - * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. - * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y - * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable - * will corresponds to the y axis. - * - * @example - * - * singleQuadrantDomainPadding={false} - * singleQuadrantDomainPadding={{ x: false }} - */ - singleQuadrantDomainPadding?: boolean | { x?: boolean; y?: boolean }; - /** - * The standalone prop determines whether the component will render a standalone svg - * or a tag that will be included in an external svg. Set standalone to false to - * compose Chart with other components within an enclosing tag. - */ - standalone?: boolean; - /** - * The startAngle props defines the overall start angle of a polar chart in degrees. This prop is used in conjunction - * with endAngle to create polar chart that spans only a segment of a circle, or to change overall rotation of the - * chart. This prop should be given as a number of degrees. Degrees are defined as starting at the 3 o'clock position, - * and proceeding counterclockwise. - */ - startAngle?: number; - /** - * The style prop defines the style of the component. The style prop should be given as an object with styles defined - * for data, labels and parent. Any valid svg styles are supported, but width, height, and padding should be specified - * via props as they determine relative layout for components in Chart. - * - * @propType { parent: object, background: object } - * @propType { parent: object, background: object } - */ - style?: Pick & { background?: VictoryStyleObject }; - /** - * The theme prop specifies a theme to use for determining styles and layout properties for a component. Any styles or - * props defined in theme may be overwritten by props specified on the component instance. - * - * @propType object - */ - theme?: ChartThemeDefinition; - /** - * Specifies the theme color. Valid values are 'blue', 'green', 'multi', etc. - * - * Note: Not compatible with theme prop - * - * @example themeColor={ChartThemeColor.blue} - */ - themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; - /** - * Specifies the width of the svg viewBox of the chart container. This value should be given as a - * number of pixels. - * - * Because Victory renders responsive containers, the width and height props do not determine the width and - * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of - * pixels will depend on the size of the container the chart is rendered into. Typically, the parent container is set - * to the same width in order to maintain the aspect ratio. - */ - width?: number; -} - -export const Chart: React.FunctionComponent = ({ - ariaDesc, - ariaTitle, - children, - legendAllowWrap = false, - legendComponent = , - legendData, - legendPosition = ChartCommonStyles.legend.position as ChartLegendPosition, - padding, - showAxis = true, - themeColor, - themeVariant, - - // destructure last - theme = getTheme(themeColor, themeVariant), - containerComponent = , - legendOrientation = theme.legend.orientation as ChartLegendOrientation, - height = theme.chart.height, - width = theme.chart.width, - ...rest -}: ChartProps) => { - const defaultPadding = { - bottom: getPaddingForSide('bottom', padding, theme.chart.padding), - left: getPaddingForSide('left', padding, theme.chart.padding), - right: getPaddingForSide('right', padding, theme.chart.padding), - top: getPaddingForSide('top', padding, theme.chart.padding) - }; - - // Clone so users can override container props - const container = React.cloneElement(containerComponent, { - desc: ariaDesc, - title: ariaTitle, - theme, - ...containerComponent.props, - className: getClassName({ className: containerComponent.props.className }) // Override VictoryContainer class name - }); - - const legend = React.cloneElement(legendComponent, { - data: legendData, - orientation: legendOrientation, - theme, - ...legendComponent.props - }); - - // Returns a computed legend - const getLegend = () => { - if (!legend.props.data) { - return null; - } - let dx = 0; - let dy = 0; - let xAxisLabelHeight = 0; - let legendTitleHeight = legend.props.title ? 10 : 0; - - // Adjust for axis label - React.Children.toArray(children).map((child: any) => { - if (child.type.role === 'axis' && child.props.label && !child.props.dependentAxis) { - xAxisLabelHeight = getLabelTextSize({ text: child.props.label, theme }).height + 10; - legendTitleHeight = 0; - } - }); - - if (legendPosition === ChartLegendPosition.bottom) { - dy += xAxisLabelHeight + legendTitleHeight; - } else if (legendPosition === ChartLegendPosition.bottomLeft) { - dy += xAxisLabelHeight + legendTitleHeight; - dx = -10; - } - - // Adjust legend position when axis is hidden - if (!showAxis) { - dy -= chart_legend_Margin.value; - } - - return getComputedLegend({ - allowWrap: legendAllowWrap, - chartType: 'chart', - dx, - dy, - height, - legendComponent: legend, - padding: defaultPadding, - position: legendPosition, - theme, - width - }); - }; - - const VictoryChartWithContainerComponent = VictoryChart as any; - - if (!showAxis) { - const Null = (): any => null; - VictoryChartWithContainerComponent.defaultProps.defaultAxes.dependent = ; - VictoryChartWithContainerComponent.defaultProps.defaultAxes.independent = ; - } - - // Note: containerComponent is required for theme - return ( - - {children} - {getLegend()} - - ); -}; -Chart.displayName = 'Chart'; - -hoistNonReactStatics(Chart, VictoryChart); diff --git a/packages/react-charts/src/components/Chart/__snapshots__/Chart.test.tsx.snap b/packages/react-charts/src/components/Chart/__snapshots__/Chart.test.tsx.snap deleted file mode 100644 index ff42c6e661d..00000000000 --- a/packages/react-charts/src/components/Chart/__snapshots__/Chart.test.tsx.snap +++ /dev/null @@ -1,9751 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Chart 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - groupComponent={} - height={300} - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} -/> -`; - -exports[`Chart 2`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - groupComponent={} - height={300} - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} -/> -`; - -exports[`renders axis and component children 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - groupComponent={} - height={200} - minDomain={ - Object { - "y": 0, - } - } - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - - - - - -`; diff --git a/packages/react-charts/src/components/Chart/index.ts b/packages/react-charts/src/components/Chart/index.ts deleted file mode 100644 index c9f6de63fe9..00000000000 --- a/packages/react-charts/src/components/Chart/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Chart'; diff --git a/packages/react-charts/src/components/ChartArea/ChartArea.test.tsx b/packages/react-charts/src/components/ChartArea/ChartArea.test.tsx deleted file mode 100644 index 5121379a058..00000000000 --- a/packages/react-charts/src/components/ChartArea/ChartArea.test.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartArea } from '../ChartArea'; - -Object.values([true, false]).forEach(() => { - test('ChartArea', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartArea/__snapshots__/ChartArea.test.tsx.snap b/packages/react-charts/src/components/ChartArea/__snapshots__/ChartArea.test.tsx.snap deleted file mode 100644 index a2367d09d9d..00000000000 --- a/packages/react-charts/src/components/ChartArea/__snapshots__/ChartArea.test.tsx.snap +++ /dev/null @@ -1,2842 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartArea 1`] = ` - - } - dataComponent={ - } - pathComponent={} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - } - clipPathComponent={} - groupComponent={} - rectComponent={} - /> - } - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - renderInPortal={true} - textComponent={} - tspanComponent={} - /> - } - samples={50} - sortKey="x" - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartArea 2`] = ` - - } - dataComponent={ - } - pathComponent={} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - } - clipPathComponent={} - groupComponent={} - rectComponent={} - /> - } - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - renderInPortal={true} - textComponent={} - tspanComponent={} - /> - } - samples={50} - sortKey="x" - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders component data 1`] = ` - - } - data={ - Array [ - Object { - "name": "Cats", - "x": 1, - "y": 1, - }, - Object { - "name": "Cats", - "x": 2, - "y": 2, - }, - Object { - "name": "Cats", - "x": 3, - "y": 3.2, - }, - Object { - "name": "Cats", - "x": 4, - "y": 3.5, - }, - ] - } - dataComponent={ - } - pathComponent={} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - } - clipPathComponent={} - groupComponent={} - rectComponent={} - /> - } - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - renderInPortal={true} - textComponent={} - tspanComponent={} - /> - } - samples={50} - sortKey="x" - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; diff --git a/packages/react-charts/src/components/ChartArea/examples/ChartArea.md b/packages/react-charts/src/components/ChartArea/examples/ChartArea.md deleted file mode 100644 index b2cae8eb915..00000000000 --- a/packages/react-charts/src/components/ChartArea/examples/ChartArea.md +++ /dev/null @@ -1,283 +0,0 @@ ---- -id: Area chart -section: charts -propComponents: [ - 'Chart', - 'ChartArea', - 'ChartAxis', - 'ChartGroup', - 'ChartThreshold', - 'ChartVoronoiContainer', -] -hideDarkMode: true ---- - -import { Chart, ChartArea, ChartAxis, ChartGroup, ChartThreshold, ChartThemeColor, ChartLegendTooltip, ChartThemeVariant, ChartVoronoiContainer, createContainer, getResizeObserver } from '@patternfly/react-charts'; -import '@patternfly/patternfly/patternfly-charts.css'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build an area chart using a Katacoda tutorial starting with a simple chart, adding multiple datasets, tooltips, axis labels, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/area-chart) - -## Examples -### Basic with right aligned legend -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // Required for mix-blend-mode CSS property - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]} - legendOrientation="vertical" - legendPosition="right" - height={200} - maxDomain={{y: 9}} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - width={800} - > - - - - - - - - -
    -``` - -### Cyan with bottom aligned legend and axis label - -This demonstrates how to combine cursor and voronoi containers to display tooltips along with a cursor. - -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartGroup, ChartThemeColor, ChartLegendTooltip, ChartVoronoiContainer, createContainer } from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // Required for mix-blend-mode CSS property - -class BottomAlignedLegend extends React.Component { - render() { - // Note: Container order is important - const CursorVoronoiContainer = createContainer("voronoi", "cursor"); - const legendData = [{ childName: 'cats', name: 'Cats' }, { childName: 'dogs', name: 'Dogs' }, { childName: 'birds', name: 'Birds' }]; - - return ( -
    - `${datum.y}`} - labelComponent={ datum.x}/>} - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - } - legendData={legendData} - legendPosition="bottom" - height={250} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50, - }} - maxDomain={{y: 9}} - themeColor={ChartThemeColor.cyan} - width={650} - > - - - - - - - - -
    - ); - } -} -``` - -### Multi-color (unordered) bottom-left aligned legend and responsive container -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartGroup, ChartThemeColor, ChartVoronoiContainer, getResizeObserver } from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // Required for mix-blend-mode CSS property - -class MultiColorChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if (this.containerRef.current && this.containerRef.current.clientWidth) { - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - - return ( -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]} - legendPosition="bottom-left" - height={225} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50, - }} - maxDomain={{y: 9}} - themeColor={ChartThemeColor.multiUnordered} - width={width} - > - - - - - - - - -
    - ); - } -} -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` -- The `theme` and `themeColor` props should be applied at the most top level component -- Use `ChartGroup` to apply theme color scales and other properties to multiple components - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) - - For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) - - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) - - For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) - - For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/components/ChartArea/index.ts b/packages/react-charts/src/components/ChartArea/index.ts deleted file mode 100644 index 30f5fe3b11c..00000000000 --- a/packages/react-charts/src/components/ChartArea/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartArea'; diff --git a/packages/react-charts/src/components/ChartAxis/ChartAxis.test.tsx b/packages/react-charts/src/components/ChartAxis/ChartAxis.test.tsx deleted file mode 100644 index 84b82b8c4d6..00000000000 --- a/packages/react-charts/src/components/ChartAxis/ChartAxis.test.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Chart } from '../Chart'; -import { ChartAxis } from './ChartAxis'; -import { ChartGroup } from '../ChartGroup'; -import { ChartLine } from '../ChartLine'; - -Object.values([true, false]).forEach(() => { - test('ChartAxis', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - - - - - - - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartAxis/__snapshots__/ChartAxis.test.tsx.snap b/packages/react-charts/src/components/ChartAxis/__snapshots__/ChartAxis.test.tsx.snap deleted file mode 100644 index 072af68fd2d..00000000000 --- a/packages/react-charts/src/components/ChartAxis/__snapshots__/ChartAxis.test.tsx.snap +++ /dev/null @@ -1,5251 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartAxis 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } -/> -`; - -exports[`ChartAxis 2`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } -/> -`; - -exports[`renders component data 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - domainPadding={ - Object { - "x": Array [ - 30, - 25, - ], - } - } - groupComponent={} - height={200} - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={300} -> - - - - - - - - - -`; diff --git a/packages/react-charts/src/components/ChartAxis/index.ts b/packages/react-charts/src/components/ChartAxis/index.ts deleted file mode 100644 index b2a015bdef6..00000000000 --- a/packages/react-charts/src/components/ChartAxis/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartAxis'; diff --git a/packages/react-charts/src/components/ChartBar/__snapshots__/ChartBar.test.tsx.snap b/packages/react-charts/src/components/ChartBar/__snapshots__/ChartBar.test.tsx.snap deleted file mode 100644 index 6d8d768f9d0..00000000000 --- a/packages/react-charts/src/components/ChartBar/__snapshots__/ChartBar.test.tsx.snap +++ /dev/null @@ -1,5228 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBar 1`] = ` - - } - data={ - Array [ - Object { - "x": 1, - "y": 1, - }, - Object { - "x": 2, - "y": 2, - }, - Object { - "x": 3, - "y": 3, - }, - Object { - "x": 4, - "y": 4, - }, - ] - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartBar 2`] = ` - - } - data={ - Array [ - Object { - "x": 1, - "y": 1, - }, - Object { - "x": 2, - "y": 2, - }, - Object { - "x": 3, - "y": 3, - }, - Object { - "x": 4, - "y": 4, - }, - ] - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders component data 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - domainPadding={ - Object { - "x": Array [ - 30, - 25, - ], - } - } - groupComponent={} - height={200} - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={300} -> - - - - - - - -`; diff --git a/packages/react-charts/src/components/ChartBar/examples/ChartBar.md b/packages/react-charts/src/components/ChartBar/examples/ChartBar.md deleted file mode 100644 index 47d845903a5..00000000000 --- a/packages/react-charts/src/components/ChartBar/examples/ChartBar.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -id: Bar chart -section: charts -propComponents: [ - 'Chart', - 'ChartAxis', - 'ChartBar', - 'ChartGroup', - 'ChartVoronoiContainer' -] -hideDarkMode: true ---- - -import { Chart, ChartAxis, ChartBar, ChartGroup, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; -import { VictoryZoomContainer } from 'victory-zoom-container'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a bar chart using a Katacoda tutorial starting with a simple chart, adding multiple datasets, tooltips, axis labels, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/bar-chart) - -## Examples -### Basic with right aligned legend -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - domain={{y: [0,9]}} - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} - legendOrientation="vertical" - legendPosition="right" - height={250} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - width={600} - > - - - - - - - - - -
    -``` - -### Purple with bottom aligned legend -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartGroup, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom" - height={275} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.purple} - width={450} - > - - - - - - - - - -
    -``` - -### Multi-color (ordered) with bottom-left aligned legend - -This demonstrates zoom for both the x and y axis. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartGroup, ChartThemeColor } from '@patternfly/react-charts'; -import { VictoryZoomContainer } from 'victory-zoom-container'; - -
    - } - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom-left" - height={400} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 100, // Adjusted to accommodate tooltip - top: 50 - }} - themeColor={ChartThemeColor.multiOrdered} - width={450} - > - - - - - - - - - -
    -``` - -### Single with right aligned legend -```js -import React from 'react'; -import { Chart, ChartBar, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - domain={{y: [0,9]}} - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }]} - legendOrientation="vertical" - legendPosition="right" - height={250} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - width={600} - > - - -
    -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` -- The `theme` and `themeColor` props should be applied at the most top level component -- Use `ChartGroup` to apply theme color scales and other properties to multiple components - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) - - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) - - For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) - - For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) - - For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/components/ChartBar/index.ts b/packages/react-charts/src/components/ChartBar/index.ts deleted file mode 100644 index d3d6f86e27d..00000000000 --- a/packages/react-charts/src/components/ChartBar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartBar'; diff --git a/packages/react-charts/src/components/ChartBullet/ChartBullet.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBullet.test.tsx deleted file mode 100644 index f87dca60d03..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBullet.test.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBullet } from './ChartBullet'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletQualitativeRange', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - `${datum.name}: ${datum.y}`} - maxDomain={{ y: 100 }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 50 }]} - qualitativeRangeData={[ - { name: 'Range', y: 50 }, - { name: 'Range', y: 75 } - ]} - width={450} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.test.tsx deleted file mode 100644 index 4142bf4fbbe..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletComparativeErrorMeasure } from './ChartBulletComparativeErrorMeasure'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletComparativeErrorMeasure', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeMeasure.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeMeasure.test.tsx deleted file mode 100644 index 795cf6d2b9d..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeMeasure.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletComparativeMeasure } from './ChartBulletComparativeMeasure'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletComparativeMeasure', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeWarningMeasure.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeWarningMeasure.test.tsx deleted file mode 100644 index 8047d5195cc..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeWarningMeasure.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletComparativeWarningMeasure } from './ChartBulletComparativeWarningMeasure'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletComparativeZeroMeasure', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletGroupTitle.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletGroupTitle.test.tsx deleted file mode 100644 index 93a07b12a5a..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletGroupTitle.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletGroupTitle } from './ChartBulletGroupTitle'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletGroupTitle', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimaryDotMeasure.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletPrimaryDotMeasure.test.tsx deleted file mode 100644 index 34b44bcdcdc..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimaryDotMeasure.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletPrimaryDotMeasure } from './ChartBulletPrimaryDotMeasure'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletPrimaryDotMeasure', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.test.tsx deleted file mode 100644 index 35d9ad2128b..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletPrimarySegmentedMeasure } from './ChartBulletPrimarySegmentedMeasure'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletPrimarySegmentedMeasure', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletQualitativeRange.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletQualitativeRange.test.tsx deleted file mode 100644 index 03181879f73..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletQualitativeRange.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletQualitativeRange } from './ChartBulletQualitativeRange'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletQualitativeRange', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletTitle.test.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletTitle.test.tsx deleted file mode 100644 index e65bfe0c0c7..00000000000 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletTitle.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartBulletTitle } from './ChartBulletTitle'; - -Object.values([true, false]).forEach(() => { - test('ChartBulletTitle', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBullet.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBullet.test.tsx.snap deleted file mode 100644 index 810c9416a82..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBullet.test.tsx.snap +++ /dev/null @@ -1,11251 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletQualitativeRange 1`] = ` - - - - - - } - standalone={false} - width={450} - /> - - } - standalone={false} - width={450} - /> - - } - size={6} - standalone={false} - width={450} - /> - - } - standalone={false} - width={450} - /> - - } - standalone={false} - width={450} - /> - - -`; - -exports[`ChartBulletQualitativeRange 2`] = ` - - - - - - } - standalone={false} - width={450} - /> - - } - standalone={false} - width={450} - /> - - } - size={6} - standalone={false} - width={450} - /> - - } - standalone={false} - width={450} - /> - - } - standalone={false} - width={450} - /> - - -`; - -exports[`renders component data 1`] = ` - - - - - - } - labels={[Function]} - standalone={false} - width={450} - /> - - } - labels={[Function]} - standalone={false} - width={450} - /> - - } - labels={[Function]} - size={6} - standalone={false} - width={450} - /> - - } - labels={[Function]} - standalone={false} - width={450} - /> - - } - labels={[Function]} - standalone={false} - width={450} - /> - - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeErrorMeasure.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeErrorMeasure.test.tsx.snap deleted file mode 100644 index 9a933921788..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeErrorMeasure.test.tsx.snap +++ /dev/null @@ -1,1411 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletComparativeErrorMeasure 1`] = ` - - - -`; - -exports[`ChartBulletComparativeErrorMeasure 2`] = ` - - - -`; - -exports[`renders component data 1`] = ` - - - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeMeasure.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeMeasure.test.tsx.snap deleted file mode 100644 index a7950ca339c..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeMeasure.test.tsx.snap +++ /dev/null @@ -1,510 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletComparativeMeasure 1`] = ` - -`; - -exports[`ChartBulletComparativeMeasure 2`] = ` - -`; - -exports[`renders component data 1`] = ` - - - } - standalone={false} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 140, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#4f5255", - "padding": 8, - "stroke": "#4f5255", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeWarningMeasure.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeWarningMeasure.test.tsx.snap deleted file mode 100644 index f6abfcdbae2..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletComparativeWarningMeasure.test.tsx.snap +++ /dev/null @@ -1,1411 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletComparativeZeroMeasure 1`] = ` - - - -`; - -exports[`ChartBulletComparativeZeroMeasure 2`] = ` - - - -`; - -exports[`renders component data 1`] = ` - - - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletGroupTitle.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletGroupTitle.test.tsx.snap deleted file mode 100644 index ce21bc31cb0..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletGroupTitle.test.tsx.snap +++ /dev/null @@ -1,61 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletGroupTitle 1`] = ` - -`; - -exports[`ChartBulletGroupTitle 2`] = ` - -`; - -exports[`renders component data 1`] = ` - - - - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletPrimaryDotMeasure.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletPrimaryDotMeasure.test.tsx.snap deleted file mode 100644 index fe12f215fc5..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletPrimaryDotMeasure.test.tsx.snap +++ /dev/null @@ -1,1505 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletPrimaryDotMeasure 1`] = ` - -`; - -exports[`ChartBulletPrimaryDotMeasure 2`] = ` - -`; - -exports[`renders component data 1`] = ` - - - } - size={6} - standalone={false} - style={ - Object { - "data": Object { - "fill": "#06c", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - - } - size={6} - standalone={false} - style={ - Object { - "data": Object { - "fill": "#06c", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - - } - size={6} - standalone={false} - style={ - Object { - "data": Object { - "fill": "#06c", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletPrimarySegmentedMeasure.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletPrimarySegmentedMeasure.test.tsx.snap deleted file mode 100644 index 03fb6db21f8..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletPrimarySegmentedMeasure.test.tsx.snap +++ /dev/null @@ -1,1499 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletPrimarySegmentedMeasure 1`] = ` - -`; - -exports[`ChartBulletPrimarySegmentedMeasure 2`] = ` - -`; - -exports[`renders component data 1`] = ` - - - } - standalone={false} - style={ - Object { - "data": Object { - "fill": "#002f5d", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - - } - standalone={false} - style={ - Object { - "data": Object { - "fill": "#8bc1f7", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - - } - standalone={false} - style={ - Object { - "data": Object { - "fill": "#06c", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletQualitativeRange.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletQualitativeRange.test.tsx.snap deleted file mode 100644 index 4056ce7295d..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletQualitativeRange.test.tsx.snap +++ /dev/null @@ -1,1499 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletQualitativeRange 1`] = ` - -`; - -exports[`ChartBulletQualitativeRange 2`] = ` - -`; - -exports[`renders component data 1`] = ` - - - } - standalone={false} - style={ - Object { - "data": Object { - "fill": "#b8bbbe", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#f0f0f0", - "#d2d2d2", - "#b8bbbe", - "#8a8d90", - "#6a6e73", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - - } - standalone={false} - style={ - Object { - "data": Object { - "fill": "#d2d2d2", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#f0f0f0", - "#d2d2d2", - "#b8bbbe", - "#8a8d90", - "#6a6e73", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - - } - standalone={false} - style={ - Object { - "data": Object { - "fill": "#f0f0f0", - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#f0f0f0", - "#d2d2d2", - "#b8bbbe", - "#8a8d90", - "#6a6e73", - ], - "height": 140, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} - /> - -`; diff --git a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletTitle.test.tsx.snap b/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletTitle.test.tsx.snap deleted file mode 100644 index 3c8ab836156..00000000000 --- a/packages/react-charts/src/components/ChartBullet/__snapshots__/ChartBulletTitle.test.tsx.snap +++ /dev/null @@ -1,83 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartBulletTitle 1`] = ` - - - -`; - -exports[`ChartBulletTitle 2`] = ` - - - -`; - -exports[`renders component data 1`] = ` - - - -`; diff --git a/packages/react-charts/src/components/ChartBullet/examples/ChartBullet.md b/packages/react-charts/src/components/ChartBullet/examples/ChartBullet.md deleted file mode 100644 index bcbc5e0db16..00000000000 --- a/packages/react-charts/src/components/ChartBullet/examples/ChartBullet.md +++ /dev/null @@ -1,908 +0,0 @@ ---- -id: Bullet chart -section: charts -propComponents: [ - 'ChartAxis', - 'ChartBullet', - 'ChartContainer' -] -hideDarkMode: true ---- - -import { ChartAxis, ChartBullet, ChartContainer, ChartThemeColor, getResizeObserver } from '@patternfly/react-charts'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a bullet chart using a Katacoda tutorial starting with a simple chart, adding qualitative ranges, primary comparative measures, a comparative warning measure, tooltips, labels, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/bullet-chart) - -## Examples -### Basic -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - primarySegmentedMeasureData={[{ name: 'Measure', y: 60 }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - width={600} - /> -
    -``` - -### Segmented primary measure -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 50, - left: 150, // Adjusted to accommodate labels - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - width={600} - /> -
    -``` - -### Responsive container with bottom aligned legend - -This demonstrates a responsive legend which wraps when items are wider than its container. - -```js -import React from 'react'; -import { ChartBullet, getResizeObserver } from '@patternfly/react-charts'; - -class BulletChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if (this.containerRef.current && this.containerRef.current.clientWidth) { - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - return ( -
    - `${datum.name}: ${datum.y}`} - legendAllowWrap={true} - legendPosition="bottom-left" - maxDomain={{y: 100}} - padding={{ - bottom: 50, - left: 50, - right: 50, - top: 100 // Adjusted to accommodate labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - titlePosition="top-left" - width={width} - /> -
    - ); - } -} -``` - -### Primary measure dot -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 50, - left: 150, // Adjusted to accommodate labels - right: 50, - top: 50 - }} - primaryDotMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - primaryDotMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - width={600} - /> -
    -``` - -### Error measure and custom axis ticks - -This is a green bullet chart with error measure and custom axis ticks with 3 legend items per row. - -```js -import React from 'react'; -import { ChartAxis, ChartBullet } from '@patternfly/react-charts'; - -
    - } - comparativeErrorMeasureData={[{name: 'Error', y: 120}]} - comparativeErrorMeasureLegendData={[{ name: 'Error' }]} - comparativeWarningMeasureData={[{name: 'Warning', y: 80}]} - comparativeWarningMeasureLegendData={[{ name: 'Warning' }]} - constrainToVisibleArea - height={200} - labels={({ datum }) => `${datum.name}: ${datum.y}`} - legendItemsPerRow={3} - padding={{ - bottom: 50, - left: 150, // Adjusted to accommodate labels - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 75 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 65 }, { name: 'Range', y: 100 }, { name: 'Range', y: 150 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - themeColor={ChartThemeColor.green} - subTitle="Measure details" - title="Text label" - width={600} - /> -
    -``` - -### Primary measure outside range - -This is a gold bullet chart with primary measure greater than max range. - -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - height={200} - maxDomain={{y: 125}} - minDomain={{y: 50}} - padding={{ - bottom: 50, - left: 150, // Adjusted to accommodate labels - right: 75, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 75 }, { name: 'Measure', y: 135 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 85 }, { name: 'Range', y: 125 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - themeColor={ChartThemeColor.gold} - subTitle="Measure details" - title="Text label" - width={600} - /> -
    -``` - -### Negative primary measure - -This bullet chart with negative primary measure is for measures considered to be bad when they are low. - -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - maxDomain={{y: 75}} - minDomain={{y: -25}} - padding={{ - bottom: 50, - left: 150, // Adjusted to accommodate labels - right: 50, - top: 65 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: -15 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }]} - qualitativeRangeData={[{ name: 'Range', y: 25, y0: -25 }, { name: 'Range', y: 50 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - width={600} - /> -
    -``` - -### Reversed with right aligned legend - -This reversed bullet chart with right aligned legend is for measures considered to be good when they are low. - -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - legendPosition="right" - legendOrientation="vertical" - maxDomain={{y: 0}} - minDomain={{y: -100}} - padding={{ - bottom: 50, - left: 150, // Adjusted to accommodate labels - right: 150, // Adjusted to accommodate legend - top: 80 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: -60 }, { name: 'Measure', y: -25 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: -50 }, { name: 'Range', y: -75 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - width={700} - /> -
    -``` - -### Negative and positive primary measures - -This bullet chart with negative and positive primary measures has 4 legend items per row. - -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - legendItemsPerRow={4} - maxDomain={{y: 75}} - minDomain={{y: -25}} - padding={{ - bottom: 50, - left: 150, // Adjusted to accommodate labels - right: 50, - top: 65 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: -10 }, { name: 'Measure', y: -20 }, { name: 'Measure', y: 10 }, { name: 'Measure', y: 40 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }, { name: 'Measure 3' }, { name: 'Measure 4' }]} - qualitativeRangeData={[{ name: 'Range', y: 25, y0: -25 }, { name: 'Range', y: 50 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - width={600} - /> -
    -``` - -### Vertical with segmented primary measure -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 400, - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - width={500} - /> -
    -``` - -### Vertical primary measure outside max range -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - maxDomain={{y: 125}} - minDomain={{y: 50}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 400, - right: 50, - top: 50 // Adjusted to accommodate primary segmented measure tooltip - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 75 }, { name: 'Measure', y: 135 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 85 }, { name: 'Range', y: 125 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - themeColor={ChartThemeColor.gold} - width={500} - /> -
    -``` - -### Custom labels -```js -import React from 'react'; -import { ChartAxis, ChartBullet } from '@patternfly/react-charts'; - -
    - { - switch (val) { - case 0: - return 'New'; - case 25: - return 'Beginner'; - case 50: - return 'Intermediate'; - case 75: - return 'Advanced'; - case 100: - return 'Expert'; - } - }} - /> - } - comparativeWarningMeasureData={[{ name: 'Warning', y: 88 }]} - constrainToVisibleArea - height={150} - labels={({ datum }) => `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - primarySegmentedMeasureData={[{ name: 'Measure', y: 60 }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - width={600} - /> -
    -``` - -### Custom size -```js -import React from 'react'; -import { ChartBullet } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 50, - left: 150, // Adjusted to accomodate labels - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 60 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - width={600} - /> -
    -``` - -### Horizontal group -```js -import React from 'react'; -import { ChartBullet, ChartContainer } from '@patternfly/react-charts'; - -
    - - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 75 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 300 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 525 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 35 }, { name: 'Measure', y: 70 }]} - qualitativeRangeData={[{ name: 'Range', y: 60 }, { name: 'Range', y: 85 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 750 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - -
    -``` - -### Vertical group -```js -import React from 'react'; -import { ChartBullet, ChartContainer } from '@patternfly/react-charts'; - -
    - - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 300, - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 550, - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 35 }, { name: 'Measure', y: 70 }]} - qualitativeRangeData={[{ name: 'Range', y: 60 }, { name: 'Range', y: 85 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 800, - right: 50, - top: 50 - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - -
    -``` - -### Horizontal group with title -```js -import React from 'react'; -import { ChartBullet, ChartContainer } from '@patternfly/react-charts'; - -
    - - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 275 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 500 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 725 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 35 }, { name: 'Measure', y: 70 }]} - qualitativeRangeData={[{ name: 'Range', y: 60 }, { name: 'Range', y: 85 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 100, // Adjusted to accommodate legend - left: 150, // Adjusted to accommodate labels - right: 50, - top: 950 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={600} - /> - -
    -``` - -### Vertical group with title -```js -import React from 'react'; -import { ChartBullet, ChartContainer } from '@patternfly/react-charts'; - -
    - - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 150 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 300, - right: 50, - top: 150 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 550, - right: 50, - top: 150 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 35 }, { name: 'Measure', y: 70 }]} - qualitativeRangeData={[{ name: 'Range', y: 60 }, { name: 'Range', y: 85 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - `${datum.name}: ${datum.y}`} - maxDomain={{y: 100}} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 800, - right: 50, - top: 150 // Adjusted to accommodate group labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 15 }, { name: 'Measure', y: 50 }]} - qualitativeRangeData={[{ name: 'Range', y: 40 }, { name: 'Range', y: 65 }]} - standalone={false} - subTitle="Measure details" - title="Text label" - width={500} - /> - -
    -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- `ChartLegend` may be used as a standalone component, instead of using `legendData` - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) - - For `ChartBullet` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) - - For `ChartContainer` props, see [VictoryContainer](https://formidable.com/open-source/victory/docs/victory-container) diff --git a/packages/react-charts/src/components/ChartBullet/index.ts b/packages/react-charts/src/components/ChartBullet/index.ts deleted file mode 100644 index cb27cc0a4ca..00000000000 --- a/packages/react-charts/src/components/ChartBullet/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './ChartBullet'; -export * from './ChartBulletComparativeErrorMeasure'; -export * from './ChartBulletComparativeMeasure'; -export * from './ChartBulletComparativeWarningMeasure'; -export * from './ChartBulletPrimaryDotMeasure'; -export * from './ChartBulletPrimarySegmentedMeasure'; -export * from './ChartBulletQualitativeRange'; diff --git a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-size.ts b/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-size.ts deleted file mode 100644 index 4b71e3f0e93..00000000000 --- a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-size.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { ChartThemeDefinition } from '../../ChartTheme'; -import { ChartBulletStyles } from '../../ChartTheme'; -import { - getBulletComparativeErrorMeasureTheme, - getBulletComparativeMeasureTheme, - getBulletComparativeWarningMeasureTheme, - getBulletPrimaryDotMeasureTheme, - getBulletPrimarySegmentedMeasureTheme, - getBulletQualitativeRangeTheme -} from '../../ChartUtils'; - -interface ChartBulletScaleInterface { - defaultSize: number; // The default chart size from the theme - height: number; // The chart height -- not SVG height - horizontal?: boolean; // Flag indicating chart is shown horizontally - scale?: number; // The scale factor to reduce / increase the bar width - value: number; // The bar height or scatter size from the theme - width: number; // The chart width -- not SVG width -} - -const scaleDimensions = ({ - defaultSize, - height, - horizontal = true, - scale = 1, - value, - width -}: ChartBulletScaleInterface) => { - if (horizontal && height > defaultSize) { - return value + (height - defaultSize) * scale; - } else if (horizontal) { - return value - (defaultSize - height) * scale; - } else if (width > defaultSize) { - return value + (width - defaultSize) * scale; - } - return value - (defaultSize - width) * scale; -}; - -// Scale bar width per the given size properties -export const scaleBarWidth = (props: ChartBulletScaleInterface) => Math.max(scaleDimensions(props), 0); - -// Scale size per the given size properties -export const scaleSize = ({ value, ...rest }: ChartBulletScaleInterface) => - Math.round( - scaleDimensions({ - scale: 1 / value, - value, - ...rest - }) - ); - -interface ChartBulletSizeInterface { - height: number; // The chart height -- not SVG height - horizontal?: boolean; // Flag indicating chart is shown horizontally - theme?: ChartThemeDefinition; - themeColor?: string; - themeVariant?: string; - width: number; // The chart width -- not SVG width -} - -export const getComparativeMeasureErrorWidth = ({ - height, - horizontal, - themeColor, - themeVariant, - width, - - // destructure last - theme = getBulletComparativeErrorMeasureTheme(themeColor, themeVariant) -}: ChartBulletSizeInterface) => - scaleBarWidth({ - defaultSize: theme.bar.height, - height, - horizontal, - value: ChartBulletStyles.comparativeMeasureErrorWidth, - width - }); - -export const getComparativeMeasureWidth = ({ - height, - horizontal, - themeColor, - themeVariant, - width, - - // destructure last - theme = getBulletComparativeMeasureTheme(themeColor, themeVariant) -}: ChartBulletSizeInterface) => - scaleBarWidth({ - defaultSize: theme.bar.height, - height, - horizontal, - value: ChartBulletStyles.comparativeMeasureWidth, - width - }); - -export const getComparativeMeasureWarningWidth = ({ - height, - horizontal, - themeColor, - themeVariant, - width, - - // destructure last - theme = getBulletComparativeWarningMeasureTheme(themeColor, themeVariant) -}: ChartBulletSizeInterface) => - scaleBarWidth({ - defaultSize: theme.bar.height, - height, - horizontal, - value: ChartBulletStyles.comparativeMeasureWarningWidth, - width - }); - -export const getPrimaryDotMeasureSize = ({ - height, - horizontal, - themeColor, - themeVariant, - width, - - // destructure last - theme = getBulletPrimaryDotMeasureTheme(themeColor, themeVariant) -}: ChartBulletSizeInterface) => - scaleSize({ - defaultSize: theme.group.height, - height, - horizontal, - value: ChartBulletStyles.primaryDotMeasureSize, - width - }); - -export const getPrimarySegmentedMeasureWidth = ({ - height, - horizontal, - themeColor, - themeVariant, - width, - - // destructure last - theme = getBulletPrimarySegmentedMeasureTheme(themeColor, themeVariant) -}: ChartBulletSizeInterface) => - scaleBarWidth({ - defaultSize: theme.group.height, - height, - horizontal, - scale: 0.3, - value: ChartBulletStyles.primarySegmentedMeasureWidth, - width - }); - -export const getQualitativeRangeBarWidth = ({ - height, - horizontal, - themeColor, - themeVariant, - width, - - // destructure last - theme = getBulletQualitativeRangeTheme(themeColor, themeVariant) -}: ChartBulletSizeInterface) => - scaleBarWidth({ - defaultSize: theme.group.height, - height, - horizontal, - value: ChartBulletStyles.qualitativeRangeWidth, - width - }); diff --git a/packages/react-charts/src/components/ChartBullet/utils/index.ts b/packages/react-charts/src/components/ChartBullet/utils/index.ts deleted file mode 100644 index 2faa24d3548..00000000000 --- a/packages/react-charts/src/components/ChartBullet/utils/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './chart-bullet-data'; -export * from './chart-bullet-domain'; -export * from './chart-bullet-size'; -export * from './chart-bullet-theme'; diff --git a/packages/react-charts/src/components/ChartContainer/ChartContainer.test.tsx b/packages/react-charts/src/components/ChartContainer/ChartContainer.test.tsx deleted file mode 100644 index a7ded650c0b..00000000000 --- a/packages/react-charts/src/components/ChartContainer/ChartContainer.test.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartContainer } from './ChartContainer'; -import { ChartLegend } from '../ChartLegend'; - -Object.values([true, false]).forEach(() => { - test('ChartContainer', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders container via ChartLegend', () => { - const view = shallow( - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartContainer/__snapshots__/ChartContainer.test.tsx.snap b/packages/react-charts/src/components/ChartContainer/__snapshots__/ChartContainer.test.tsx.snap deleted file mode 100644 index cf0c6944e3a..00000000000 --- a/packages/react-charts/src/components/ChartContainer/__snapshots__/ChartContainer.test.tsx.snap +++ /dev/null @@ -1,1395 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartContainer 1`] = ` -} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartContainer 2`] = ` -} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders container via ChartLegend 1`] = ` -} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -> - - -`; diff --git a/packages/react-charts/src/components/ChartContainer/index.ts b/packages/react-charts/src/components/ChartContainer/index.ts deleted file mode 100644 index d5acc9b1911..00000000000 --- a/packages/react-charts/src/components/ChartContainer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartContainer'; diff --git a/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.test.tsx b/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.test.tsx deleted file mode 100644 index ad045717f9b..00000000000 --- a/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.test.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartArea } from '../ChartArea'; -import { ChartGroup } from '../ChartGroup'; -import { ChartCursorContainer } from './ChartCursorContainer'; - -Object.values([true, false]).forEach(() => { - test('ChartVoronoiContainer', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders container via ChartGroup', () => { - const view = shallow( - } height={200} width={200}> - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartCursorContainer/__snapshots__/ChartCursorContainer.test.tsx.snap b/packages/react-charts/src/components/ChartCursorContainer/__snapshots__/ChartCursorContainer.test.tsx.snap deleted file mode 100644 index 81fd083c0ba..00000000000 --- a/packages/react-charts/src/components/ChartCursorContainer/__snapshots__/ChartCursorContainer.test.tsx.snap +++ /dev/null @@ -1,2865 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartVoronoiContainer 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - cursorLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - tspanComponent={} - /> - } - cursorLabelOffset={ - Object { - "x": 5, - "y": -10, - } - } - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartVoronoiContainer 2`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - cursorLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - tspanComponent={} - /> - } - cursorLabelOffset={ - Object { - "x": 5, - "y": -10, - } - } - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders container via ChartGroup 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - cursorLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - cursorLabelOffset={ - Object { - "x": 5, - "y": -10, - } - } - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - /> - } - groupComponent={} - height={200} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - -`; diff --git a/packages/react-charts/src/components/ChartCursorContainer/index.ts b/packages/react-charts/src/components/ChartCursorContainer/index.ts deleted file mode 100644 index 4771ace315f..00000000000 --- a/packages/react-charts/src/components/ChartCursorContainer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartCursorContainer'; diff --git a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorFlyout.test.tsx b/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorFlyout.test.tsx deleted file mode 100644 index 61198f92b1e..00000000000 --- a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorFlyout.test.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartArea } from '../ChartArea'; -import { ChartGroup } from '../ChartGroup'; -import { ChartCursorFlyout } from './ChartCursorFlyout'; -import { ChartCursorTooltip } from './ChartCursorTooltip'; -import { createContainer } from '../ChartUtils'; - -Object.values([true, false]).forEach(() => { - test('ChartTooltip', () => { - const view = shallow(} />); - expect(view).toMatchSnapshot(); - }); -}); - -test('allows tooltip via container component', () => { - const CursorVoronoiContainer = createContainer('cursor', 'voronoi'); - const view = shallow( - 'y: ' + point.y} - labelComponent={} />} - /> - } - height={200} - width={200} - > - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.test.tsx b/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.test.tsx deleted file mode 100644 index fd2d5079e18..00000000000 --- a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.test.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartArea } from '../ChartArea'; -import { ChartGroup } from '../ChartGroup'; -import { ChartCursorTooltip } from './ChartCursorTooltip'; -import { createContainer } from '../ChartUtils'; - -Object.values([true, false]).forEach(() => { - test('ChartCursorTooltip', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('allows tooltip via container component', () => { - const CursorVoronoiContainer = createContainer('cursor', 'voronoi'); - const view = shallow( - 'y: ' + point.y} labelComponent={} /> - } - height={200} - width={200} - > - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorFlyout.test.tsx.snap b/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorFlyout.test.tsx.snap deleted file mode 100644 index 968805fab7f..00000000000 --- a/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorFlyout.test.tsx.snap +++ /dev/null @@ -1,1968 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartTooltip 1`] = ` -} - pointerLength={10} - pointerWidth={20} - role="presentation" - shapeRendering="auto" - /> - } - labelComponent={} - labelTextAnchor="start" - pointerOrientation={[Function]} - style={ - Object { - "textAnchor": "start", - } - } - text="This is a tooltip" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartTooltip 2`] = ` -} - pointerLength={10} - pointerWidth={20} - role="presentation" - shapeRendering="auto" - /> - } - labelComponent={} - labelTextAnchor="start" - pointerOrientation={[Function]} - style={ - Object { - "textAnchor": "start", - } - } - text="This is a tooltip" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`allows tooltip via container component 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - cursorLabelComponent={ - - } - cursorLabelOffset={ - Object { - "x": 5, - "y": -10, - } - } - labelComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - /> - } - labels={[Function]} - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - voronoiPadding={5} - /> - } - groupComponent={} - height={200} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - -`; diff --git a/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorTooltip.test.tsx.snap b/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorTooltip.test.tsx.snap deleted file mode 100644 index b9815cc49c7..00000000000 --- a/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorTooltip.test.tsx.snap +++ /dev/null @@ -1,1958 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartCursorTooltip 1`] = ` -} - pointerLength={10} - pointerWidth={20} - role="presentation" - shapeRendering="auto" - /> - } - labelComponent={} - labelTextAnchor="start" - pointerOrientation={[Function]} - style={ - Object { - "textAnchor": "start", - } - } - text="This is a tooltip" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartCursorTooltip 2`] = ` -} - pointerLength={10} - pointerWidth={20} - role="presentation" - shapeRendering="auto" - /> - } - labelComponent={} - labelTextAnchor="start" - pointerOrientation={[Function]} - style={ - Object { - "textAnchor": "start", - } - } - text="This is a tooltip" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`allows tooltip via container component 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - cursorLabelComponent={ - - } - cursorLabelOffset={ - Object { - "x": 5, - "y": -10, - } - } - labelComponent={} - labels={[Function]} - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - voronoiPadding={5} - /> - } - groupComponent={} - height={200} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - -`; diff --git a/packages/react-charts/src/components/ChartCursorTooltip/index.ts b/packages/react-charts/src/components/ChartCursorTooltip/index.ts deleted file mode 100644 index 2bbe3324791..00000000000 --- a/packages/react-charts/src/components/ChartCursorTooltip/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './ChartCursorFlyout'; -export * from './ChartCursorTooltip'; diff --git a/packages/react-charts/src/components/ChartDonut/ChartDonut.test.tsx b/packages/react-charts/src/components/ChartDonut/ChartDonut.test.tsx deleted file mode 100644 index 8f64f7a0abb..00000000000 --- a/packages/react-charts/src/components/ChartDonut/ChartDonut.test.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartDonut } from './ChartDonut'; - -Object.values([true, false]).forEach(() => { - test('ChartDonut', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartDonut/__snapshots__/ChartDonut.test.tsx.snap b/packages/react-charts/src/components/ChartDonut/__snapshots__/ChartDonut.test.tsx.snap deleted file mode 100644 index 15a9cbf0a01..00000000000 --- a/packages/react-charts/src/components/ChartDonut/__snapshots__/ChartDonut.test.tsx.snap +++ /dev/null @@ -1,2780 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartDonut 1`] = ` - - - - - -`; - -exports[`ChartDonut 2`] = ` - - - - - -`; - -exports[`renders component data 1`] = ` - - - - - -`; diff --git a/packages/react-charts/src/components/ChartDonut/examples/ChartDonut.md b/packages/react-charts/src/components/ChartDonut/examples/ChartDonut.md deleted file mode 100644 index ce3076848b6..00000000000 --- a/packages/react-charts/src/components/ChartDonut/examples/ChartDonut.md +++ /dev/null @@ -1,245 +0,0 @@ ---- -id: Donut chart -section: charts -propComponents: [ - 'ChartDonut' -] -hideDarkMode: true ---- - -import { ChartDonut, ChartThemeColor, ChartThemeVariant } from '@patternfly/react-charts'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a donut chart using a Katacoda tutorial starting with a simple chart, adding thresholds, tooltips, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/donut-chart) - -## Examples -### Basic -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - subTitle="Pets" - title="100" - /> -
    -``` - -### Right aligned legend -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 140, // Adjusted to accommodate legend - top: 20 - }} - subTitle="Pets" - title="100" - width={350} - /> -
    -``` - -### Multi-color (ordered) with right aligned legend -```js -import React from 'react'; -import { ChartDonut, ChartThemeColor, ChartThemeVariant } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 140, // Adjusted to accommodate legend - top: 20 - }} - subTitle="Pets" - title="100" - themeColor={ChartThemeColor.multiOrdered} - width={350} - /> -
    -``` - -### Bottom aligned legend -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendPosition="bottom" - legendWidth={225} - padding={{ - bottom: 65, // Adjusted to accommodate legend - left: 20, - right: 20, - top: 20 - }} - subTitle="Pets" - title="100" - width={300} - /> -
    -``` - -### Small -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - subTitle="Pets" - title="100" - width={150} - /> -
    -``` - -### Small with right aligned legend -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 145, // Adjusted to accommodate legend - top: 20 - }} - subTitle="Pets" - title="100" - width={275} - /> -
    -``` - -### Small with bottom aligned subtitle -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 25, // Adjusted to accommodate subTitle - left: 20, - right: 145, // Adjusted to accommodate legend - top: 20 - }} - subTitle="Pets" - subTitlePosition="bottom" - title="100" - width={275} - /> -
    -``` - -### Small with right aligned subtitle -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendPosition="bottom" - padding={{ - bottom: 70, // Adjusted to accommodate legend - left: 20, - right: 50, // Adjusted to accommodate subTitle - top: 20 - }} - subTitle="Pets" - subTitlePosition="right" - title="100" - width={300} - /> -
    -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `ChartDonut` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) diff --git a/packages/react-charts/src/components/ChartDonut/index.ts b/packages/react-charts/src/components/ChartDonut/index.ts deleted file mode 100644 index a04745387b0..00000000000 --- a/packages/react-charts/src/components/ChartDonut/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartDonut'; diff --git a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.test.tsx b/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.test.tsx deleted file mode 100644 index 1428f97d359..00000000000 --- a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.test.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartDonutThreshold } from './ChartDonutThreshold'; - -Object.values([true, false]).forEach(() => { - test('ChartDonutThreshold', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.test.tsx b/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.test.tsx deleted file mode 100644 index 0602836e966..00000000000 --- a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartDonutUtilization } from './ChartDonutUtilization'; - -Object.values([true, false]).forEach(() => { - test('ChartDonutUtilization', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartDonutUtilization/__snapshots__/ChartDonutThreshold.test.tsx.snap b/packages/react-charts/src/components/ChartDonutUtilization/__snapshots__/ChartDonutThreshold.test.tsx.snap deleted file mode 100644 index 7852b1c4c20..00000000000 --- a/packages/react-charts/src/components/ChartDonutUtilization/__snapshots__/ChartDonutThreshold.test.tsx.snap +++ /dev/null @@ -1,2815 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartDonutThreshold 1`] = ` - - - - - -`; - -exports[`ChartDonutThreshold 2`] = ` - - - - - -`; - -exports[`renders component data 1`] = ` - - - - - -`; diff --git a/packages/react-charts/src/components/ChartDonutUtilization/__snapshots__/ChartDonutUtilization.test.tsx.snap b/packages/react-charts/src/components/ChartDonutUtilization/__snapshots__/ChartDonutUtilization.test.tsx.snap deleted file mode 100644 index 187969d6af3..00000000000 --- a/packages/react-charts/src/components/ChartDonutUtilization/__snapshots__/ChartDonutUtilization.test.tsx.snap +++ /dev/null @@ -1,2764 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartDonutUtilization 1`] = ` - - - - - -`; - -exports[`ChartDonutUtilization 2`] = ` - - - - - -`; - -exports[`renders component data 1`] = ` - - - - - -`; diff --git a/packages/react-charts/src/components/ChartDonutUtilization/examples/ChartDonutUtilization.md b/packages/react-charts/src/components/ChartDonutUtilization/examples/ChartDonutUtilization.md deleted file mode 100644 index de551d0bd70..00000000000 --- a/packages/react-charts/src/components/ChartDonutUtilization/examples/ChartDonutUtilization.md +++ /dev/null @@ -1,798 +0,0 @@ ---- -id: Donut utilization chart -section: charts -propComponents: [ - 'ChartDonutThreshold', - 'ChartDonutUtilization' -] -hideDarkMode: true ---- - -import { ChartDonutThreshold, ChartDonutUtilization, ChartThemeColor, ChartThemeVariant } from '@patternfly/react-charts'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a donut utilization chart using a Katacoda tutorial starting with a simple chart, adding thresholds, tooltips, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/donut-utilization-chart) - -## Donut utilization examples -### Basic -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - subTitle="of 100 GBps" - title="75%" - /> -
    -``` - -### Right aligned legend -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -class DonutUtilizationChart extends React.Component { - constructor(props) { - super(props); - this.state = { - spacer: '', - used: 0 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - const val = (used + 10) % 100; - this.setState({ - spacer: val < 10 ? ' ' : '', - used: val - }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { spacer, used } = this.state; - return ( -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]} - legendOrientation="vertical" - padding={{ - bottom: 20, - left: 20, - right: 225, // Adjusted to accommodate legend - top: 20 - }} - subTitle="of 100 GBps" - title={`${used}%`} - thresholds={[{ value: 60 }, { value: 90 }]} - width={435} - /> -
    - ); - } -} -``` - -### Inverted with right aligned legend -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -class InvertedDonutUtilizationChart extends React.Component { - constructor(props) { - super(props); - this.state = { - spacer: '', - used: 100 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - const val = (((used - 10) % 100) + 100) % 100; - this.setState({ - spacer: val < 10 ? ' ' : '', - used: val - }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { spacer, used } = this.state; - return ( -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]} - legendOrientation="vertical" - padding={{ - bottom: 20, - left: 20, - right: 225, // Adjusted to accommodate legend - top: 20 - }} - subTitle="of 100 GBps" - title={`${used}%`} - thresholds={[{ value: 60 }, { value: 20 }]} - width={435} - /> -
    - ); - } -} -``` - -### Right aligned vertical legend -```js -import React from 'react'; -import { ChartDonutUtilization, ChartThemeColor, ChartThemeVariant } from '@patternfly/react-charts'; - -class VerticalLegendUtilizationChart extends React.Component { - constructor(props) { - super(props); - this.state = { - spacer: '', - used: 0 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - const val = (used + 10) % 100; - this.setState({ - spacer: val < 10 ? ' ' : '', - used: val - }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { spacer, used } = this.state; - return ( -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]} - legendOrientation="vertical" - legendPosition="bottom" - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 20, - right: 20, - top: 20 - }} - subTitle="of 100 GBps" - title={`${used}%`} - themeColor={ChartThemeColor.green} - thresholds={[{ value: 60 }, { value: 90 }]} - width={230} - /> -
    - ); - } -} -``` - -### Bottom aligned legend -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: 45%` }, { name: 'Unused' }]} - legendPosition="bottom" - padding={{ - bottom: 65, // Adjusted to accommodate legend - left: 20, - right: 20, - top: 20 - }} - subTitle="of 100 GBps" - title="45%" - thresholds={[{ value: 60 }, { value: 90 }]} - width={300} - /> -
    -``` - -### Small -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - subTitle="of 100 GBps" - title="75%" - width={175} - /> -
    -``` - -### Small with right aligned legend -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -class UtilizationChart extends React.Component { - constructor(props) { - super(props); - this.state = { - spacer: '', - used: 0 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - const val = (used + 10) % 100; - this.setState({ - spacer: val < 10 ? ' ' : '', - used: val - }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { spacer, used } = this.state; - return ( -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]} - legendOrientation="vertical" - padding={{ - bottom: 20, - left: 20, - right: 195, // Adjusted to accommodate legend - top: 20 - }} - subTitle="of 100 GBps" - title={`${used}%`} - thresholds={[{ value: 60 }, { value: 90 }]} - width={350} - /> -
    - ); - } -} -``` - -### Small with bottom aligned subtitle - -This is a small donut utilization chart with bottom aligned legend and right aligned subtitle. - -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: 45%` }, { name: 'Unused' }]} - legendOrientation="vertical" - padding={{ - bottom: 25, // Adjusted to accommodate subTitle - left: 20, - right: 195, // Adjusted to accommodate legend - top: 20 - }} - subTitle="of 100 GBps" - subTitlePosition="bottom" - title="45%" - thresholds={[{ value: 60 }, { value: 90 }]} - width={350} - /> -
    -``` - -### Small with right aligned subtitle -```js -import React from 'react'; -import { ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: 45%` }, { name: 'Unused' }]} - legendPosition="bottom" - padding={{ - bottom: 45, // Adjusted to accommodate legend - left: 20, - right: 20, - top: 20 - }} - subTitle="of 100 GBps" - subTitlePosition="right" - title="45%" - thresholds={[{ value: 60 }, { value: 90 }]} - width={350} - /> -
    -``` - -## Donut utilization threshold examples -### Static thresholds -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? datum.x : null} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - subTitle="of 100 GBps" - title="45%" - /> - -
    -``` - -### Static thresholds with right aligned legend -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -class ThresholdChart extends React.Component { - constructor(props) { - super(props); - this.state = { - used: 0 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - this.setState({ used: (used + 10) % 100 }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { used } = this.state; - return ( -
    - datum.x ? datum.x : null} - padding={{ - bottom: 20, - left: 20, - right: 290, // Adjusted to accommodate legend - top: 20 - }} - width={500} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${used}%` }, { name: 'Warning threshold at 60%' }, { name: 'Danger threshold at 90%' }]} - legendOrientation="vertical" - subTitle="of 100 GBps" - title={`${used}%`} - thresholds={[{ value: 60 }, { value: 90 }]} - /> - -
    - ); - } -} -``` - -### Inverted static thresholds with right aligned legend -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -class InvertedThresholdChart extends React.Component { - constructor(props) { - super(props); - this.state = { - spacer: '', - used: 100 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - const val = (((used - 10) % 100) + 100) % 100; - this.setState({ - spacer: val < 10 ? ' ' : '', - used: val - }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { used } = this.state; - return ( -
    - datum.x ? datum.x : null} - padding={{ - bottom: 20, - left: 20, - right: 290, // Adjusted to accommodate legend - top: 20 - }} - width={500} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${used}%` }, { name: 'Warning threshold at 60%' }, { name: 'Danger threshold at 20%' }]} - legendOrientation="vertical" - subTitle="of 100 GBps" - title={`${used}%`} - thresholds={[{ value: 60 }, { value: 20 }]} - /> - -
    - ); - } -} -``` - -### Static thresholds with custom legend -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization, ChartThemeColor, ChartThemeVariant } from '@patternfly/react-charts'; - -class CustomLegendThresholdChart extends React.Component { - constructor(props) { - super(props); - this.state = { - used: 0 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - this.setState({ used: (used + 10) % 100 }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { used } = this.state; - return ( -
    - datum.x ? datum.x : null} - padding={{ - bottom: 125, // Adjusted to accommodate legend - left: 20, - right: 20, - top: 20 - }} - width={230} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${used}%` }, { name: 'Warning threshold at 60%' }, { name: 'Danger threshold at 90%' }]} - legendOrientation="vertical" - legendPosition="bottom" - subTitle="of 100 GBps" - title={`${used}%`} - themeColor={ChartThemeColor.green} - thresholds={[{ value: 60 }, { value: 90 }]} - /> - -
    - ); - } -} -``` - -### Static thresholds with bottom aligned legend -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? datum.x : null} - padding={{ - bottom: 65, // Adjusted to accommodate legend - left: 20, - right: 20, - top: 20 - }} - width={675} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: 45%` }, { name: 'Warning threshold at 60%' }, { name: 'Danger threshold at 90%' }]} - legendPosition="bottom" - subTitle="of 100 GBps" - title="45%" - /> - -
    -``` - -### Small with static thresholds -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? datum.x : null} - width={185} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - subTitle="of 100 GBps" - title="45%" - /> - -
    -``` - -### Small with static thresholds and right aligned legend -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -class ThresholdChart extends React.Component { - constructor(props) { - super(props); - this.state = { - used: 0 - }; - } - - componentDidMount() { - this.interval = setInterval(() => { - const { used } = this.state; - this.setState({ used: (used + 10) % 100 }); - }, 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { used } = this.state; - return ( -
    - datum.x ? datum.x : null} - padding={{ - bottom: 20, - left: 20, - right: 260, // Adjusted to accommodate legend - top: 20 - }} - width={425} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: ${used}%` }, { name: 'Warning threshold at 60%' }, { name: 'Danger threshold at 90%' }]} - legendOrientation="vertical" - subTitle="of 100 GBps" - title={`${used}%`} - thresholds={[{ value: 60 }, { value: 90 }]} - /> - -
    - ); - } -} -``` - -### Small with subtitle - -This is a small donut utilization chart with static thresholds with right aligned legend and bottom aligned subtitle. - -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? datum.x : null} - padding={{ - bottom: 30, // Adjusted to accommodate label - left: 20, - right: 260, // Adjusted to accommodate legend - top: 20 - }} - subTitlePosition="bottom" - width={425} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: 45%` }, { name: 'Warning threshold at 60%' }, { name: 'Danger threshold at 90%' }]} - legendOrientation="vertical" - subTitle="of 100 GBps" - title="45%" - thresholds={[{ value: 60 }, { value: 90 }]} - /> - -
    -``` - -### Small with right aligned subtitle -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; - -
    - datum.x ? datum.x : null} - padding={{ - bottom: 60, // Adjusted to accommodate legend - left: 20, - right: 20, - top: 20 - }} - subTitlePosition="right" - width={675} - > - datum.x ? `${datum.x}: ${datum.y}%` : null} - legendData={[{ name: `Storage capacity: 45%` }, { name: 'Warning threshold at 60%' }, { name: 'Danger threshold at 90%' }]} - legendPosition="bottom" - subTitle="of 100 GBps" - title="45%" - thresholds={[{ value: 60 }, { value: 90 }]} - /> - -
    -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `ChartDonutThreshold` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) - - For `ChartDonutUtilization` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) diff --git a/packages/react-charts/src/components/ChartDonutUtilization/index.ts b/packages/react-charts/src/components/ChartDonutUtilization/index.ts deleted file mode 100644 index b69ee70fba9..00000000000 --- a/packages/react-charts/src/components/ChartDonutUtilization/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './ChartDonutThreshold'; -export * from './ChartDonutUtilization'; diff --git a/packages/react-charts/src/components/ChartGroup/ChartGroup.test.tsx b/packages/react-charts/src/components/ChartGroup/ChartGroup.test.tsx deleted file mode 100644 index bcfd3f74015..00000000000 --- a/packages/react-charts/src/components/ChartGroup/ChartGroup.test.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartArea } from '../ChartArea'; -import { ChartGroup } from './ChartGroup'; - -Object.values([true, false]).forEach(() => { - test('ChartGroup', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders container children', () => { - const view = shallow( - - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartGroup/__snapshots__/ChartGroup.test.tsx.snap b/packages/react-charts/src/components/ChartGroup/__snapshots__/ChartGroup.test.tsx.snap deleted file mode 100644 index 154e4d9a101..00000000000 --- a/packages/react-charts/src/components/ChartGroup/__snapshots__/ChartGroup.test.tsx.snap +++ /dev/null @@ -1,2797 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartGroup 1`] = ` - - } - groupComponent={} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartGroup 2`] = ` - - } - groupComponent={} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders container children 1`] = ` - - } - groupComponent={} - height={200} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - -`; diff --git a/packages/react-charts/src/components/ChartGroup/index.ts b/packages/react-charts/src/components/ChartGroup/index.ts deleted file mode 100644 index 1131d05e0ed..00000000000 --- a/packages/react-charts/src/components/ChartGroup/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartGroup'; diff --git a/packages/react-charts/src/components/ChartLabel/ChartLabel.test.tsx b/packages/react-charts/src/components/ChartLabel/ChartLabel.test.tsx deleted file mode 100644 index f6d0fd571bc..00000000000 --- a/packages/react-charts/src/components/ChartLabel/ChartLabel.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartLabel } from './ChartLabel'; - -Object.values([true, false]).forEach(() => { - test('ChartLabel', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component text', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartLabel/__snapshots__/ChartLabel.test.tsx.snap b/packages/react-charts/src/components/ChartLabel/__snapshots__/ChartLabel.test.tsx.snap deleted file mode 100644 index 06306ff2d50..00000000000 --- a/packages/react-charts/src/components/ChartLabel/__snapshots__/ChartLabel.test.tsx.snap +++ /dev/null @@ -1,62 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartLabel 1`] = ` -} - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - style={ - Object { - "fontFamily": "var(--pf-chart-global--FontFamily)", - "fontSize": 14, - "letterSpacing": "var(--pf-chart-global--letter-spacing)", - "textAnchor": undefined, - } - } - textComponent={} - tspanComponent={} -/> -`; - -exports[`ChartLabel 2`] = ` -} - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - style={ - Object { - "fontFamily": "var(--pf-chart-global--FontFamily)", - "fontSize": 14, - "letterSpacing": "var(--pf-chart-global--letter-spacing)", - "textAnchor": undefined, - } - } - textComponent={} - tspanComponent={} -/> -`; - -exports[`renders component text 1`] = ` -} - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - style={ - Object { - "fontFamily": "var(--pf-chart-global--FontFamily)", - "fontSize": 14, - "letterSpacing": "var(--pf-chart-global--letter-spacing)", - "textAnchor": undefined, - } - } - text="This is a test" - textComponent={} - tspanComponent={} -/> -`; diff --git a/packages/react-charts/src/components/ChartLabel/index.ts b/packages/react-charts/src/components/ChartLabel/index.ts deleted file mode 100644 index 9972e4726c3..00000000000 --- a/packages/react-charts/src/components/ChartLabel/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartLabel'; diff --git a/packages/react-charts/src/components/ChartLegend/ChartLegend.test.tsx b/packages/react-charts/src/components/ChartLegend/ChartLegend.test.tsx deleted file mode 100644 index 9aeb4b1bd89..00000000000 --- a/packages/react-charts/src/components/ChartLegend/ChartLegend.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartLegend } from './ChartLegend'; - -Object.values([true, false]).forEach(() => { - test('ChartLegend', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartLegend/__snapshots__/ChartLegend.test.tsx.snap b/packages/react-charts/src/components/ChartLegend/__snapshots__/ChartLegend.test.tsx.snap deleted file mode 100644 index 8871ed47d6e..00000000000 --- a/packages/react-charts/src/components/ChartLegend/__snapshots__/ChartLegend.test.tsx.snap +++ /dev/null @@ -1,2794 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartLegend 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - data={ - Array [ - Object { - "name": "Series 1", - }, - Object { - "name": "Series 2", - }, - ] - } - dataComponent={} - groupComponent={} - labelComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - titleComponent={} -/> -`; - -exports[`ChartLegend 2`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - data={ - Array [ - Object { - "name": "Series 1", - }, - Object { - "name": "Series 2", - }, - ] - } - dataComponent={} - groupComponent={} - labelComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - titleComponent={} -/> -`; - -exports[`renders component data 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - data={ - Array [ - Object { - "name": "Cats", - }, - Object { - "name": "Dogs", - }, - ] - } - dataComponent={} - groupComponent={} - height={50} - labelComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - title="Average number of pets" - titleComponent={} - width={200} -/> -`; diff --git a/packages/react-charts/src/components/ChartLegend/examples/ChartLegend.md b/packages/react-charts/src/components/ChartLegend/examples/ChartLegend.md deleted file mode 100644 index 665e988984a..00000000000 --- a/packages/react-charts/src/components/ChartLegend/examples/ChartLegend.md +++ /dev/null @@ -1,821 +0,0 @@ ---- -id: Legend chart -section: charts -propComponents: [ - 'ChartLegend' -] -hideDarkMode: true ---- - -import { - Chart, - ChartArea, - ChartAxis, - ChartBar, - ChartBullet, - ChartDonut, - ChartGroup, - ChartLabel, - ChartLegend, - ChartLegendTooltip, - ChartLine, - ChartPie, - ChartScatter, - ChartThemeColor, - ChartVoronoiContainer, - createContainer, - getInteractiveLegendEvents, - getInteractiveLegendItemStyles, - getResizeObserver -} from '@patternfly/react-charts'; -import chart_area_Opacity from '@patternfly/react-tokens/dist/esm/chart_area_Opacity'; -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -## Examples -### Basic with right aligned legend -```js -import React from 'react'; -import { ChartDonut } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 140, // Adjusted to accommodate legend - top: 20 - }} - subTitle="Pets" - title="100" - width={350} - /> -
    -``` - -### Bottom aligned legend -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartGroup, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom" - height={275} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.purple} - width={450} - > - - - - - - - - - -
    -``` - -### Responsive bottom-left aligned legend - -This demonstrates a responsive legend which wraps when items are wider than its container. - -```js -import React from 'react'; -import { ChartBullet, getResizeObserver } from '@patternfly/react-charts'; - -class BulletChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if(this.containerRef.current && this.containerRef.current.clientWidth){ - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - return ( -
    -
    - `${datum.name}: ${datum.y}`} - legendAllowWrap={true} - legendPosition="bottom-left" - maxDomain={{y: 100}} - padding={{ - bottom: 50, - left: 50, - right: 50, - top: 100 // Adjusted to accommodate labels - }} - primarySegmentedMeasureData={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} - primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} - qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} - qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} - subTitle="Measure details" - title="Text label" - titlePosition="top-left" - width={width} - /> -
    -
    - ); - } -} -``` - -### Standalone legend - -This demonstrates a standalone legend vs. using the `legendData` property. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLegend, ChartLine, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.green} - width={450} - > - - - - - - - - - - -
    -``` - -### Interactive legend - -This demonstrates how to add an interactive legend using events such as `onMouseOver`, `onMouseOut`, and `onClick`. - -```js -import React from 'react'; -import { - Chart, - ChartArea, - ChartAxis, - ChartGroup, - ChartLegend, - ChartLegendTooltip, - ChartScatter, - ChartThemeColor, - ChartVoronoiContainer, - createContainer, - getInteractiveLegendEvents, - getInteractiveLegendItemStyles, - getResizeObserver -} from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // For mixed blend mode - -class InteractiveLegendChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - hiddenSeries: new Set(), - width: 0 - }; - this.series = [{ - datapoints: [ - { x: '2015', y: 3 }, - { x: '2016', y: 4 }, - { x: '2017', y: 8 }, - { x: '2018', y: 6 } - ], - legendItem: { name: 'Cats' } - }, { - datapoints: [ - { x: '2015', y: 2 }, - { x: '2016', y: 3 }, - { x: '2017', y: 4 }, - { x: '2018', y: 5 }, - { x: '2019', y: 6 } - ], - legendItem: { name: 'Dogs' } - }, { - datapoints: [ - { x: '2015', y: 1 }, - { x: '2016', y: 2 }, - { x: '2017', y: 3 }, - { x: '2018', y: 2 }, - { x: '2019', y: 4 } - ], - legendItem: { name: 'Birds' } - }]; - - // Returns groups of chart names associated with each data series - this.getChartNames = () => { - const result = []; - this.series.map((_, index) => { - // Each group of chart names are hidden / shown together - result.push([`area-${index}`, `scatter-${index}`]); - }); - return result; - }; - - // Returns onMouseOver, onMouseOut, and onClick events for the interactive legend - this.getEvents = () => getInteractiveLegendEvents({ - chartNames: this.getChartNames(), - isHidden: this.isHidden, - legendName: 'legend', - onLegendClick: this.handleLegendClick - }); - - // Returns legend data styled per hiddenSeries - this.getLegendData = () => { - const { hiddenSeries } = this.state; - return this.series.map((s, index) => { - return { - childName: `area-${index}`, // Sync tooltip legend with the series associated with given chart name - ...s.legendItem, // name property - ...getInteractiveLegendItemStyles(hiddenSeries.has(index)) // hidden styles - }; - }); - }; - - // Hide each data series individually - this.handleLegendClick = (props) => { - if (!this.state.hiddenSeries.delete(props.index)) { - this.state.hiddenSeries.add(props.index); - } - this.setState({ hiddenSeries: new Set(this.state.hiddenSeries) }); - }; - - // Set chart width per current window size - this.handleResize = () => { - if (this.containerRef.current && this.containerRef.current.clientWidth) { - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - - // Returns true if data series is hidden - this.isHidden = (index) => { - const { hiddenSeries } = this.state; // Skip if already hidden - return hiddenSeries.has(index); - }; - - this.isDataAvailable = () => { - const { hiddenSeries } = this.state; - return hiddenSeries.size !== this.series.length; - }; - - // Note: Container order is important - const CursorVoronoiContainer = createContainer("voronoi", "cursor"); - - this.cursorVoronoiContainer = ( - datum.childName.includes('area-') && datum.y !== null ? `${datum.y}` : null} - labelComponent={ datum.x}/>} - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - ); - }; - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - // Tips: - // 1. Omitting hidden components will reassign color scale, use null data instead or custom colors - // 2. Set domain or tick axis labels to account for when all data series are hidden - // 3. Omit tooltip for ChartScatter component by checking childName prop - // 4. Omit tooltip when all data series are hidden - // 5. Clone original container to ensure tooltip events are not lost when data series are hidden / shown - render() { - const { hiddenSeries, width } = this.state; - - const container = React.cloneElement( - this.cursorVoronoiContainer, - { - disable: !this.isDataAvailable() - } - ); - - return ( -
    -
    - } - legendPosition="bottom-left" - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50, - }} - maxDomain={{y: 9}} - themeColor={ChartThemeColor.multiUnordered} - width={width} - > - - - - {this.series.map((s, index) => { - return ( - (active ? 5 : 3)} - /> - ); - })} - - - {this.series.map((s, index) => { - return ( - - ); - })} - - -
    -
    - ); - } -} -``` - -### Interactive legend with pie chart - -This demonstrates how to add an interactive legend to a pie chart using events such as `onMouseOver`, `onMouseOut`, and `onClick`. - -```js -import React from 'react'; -import { - Chart, - ChartLegend, - ChartThemeColor, - ChartPie, - getInteractiveLegendEvents, - getInteractiveLegendItemStyles -} from '@patternfly/react-charts'; - -class InteractivePieLegendChart extends React.Component { - constructor(props) { - super(props); - this.state = { - hiddenSeries: new Set(), - width: 0 - }; - this.series = [{ - datapoints: { x: 'Cats', y: 35 }, - legendItem: { name: 'Cats: 35' } - }, { - datapoints: { x: 'Dogs', y: 55 }, - legendItem: { name: 'Dogs: 55' } - }, { - datapoints: { x: 'Birds', y: 10 }, - legendItem: { name: 'Birds: 10' } - }]; - - // Returns groups of chart names associated with each data series - this.getChartNames = () => { - const result = []; - this.series.map((_, index) => { - // Provide names for each series hidden / shown -- use the same name for a pie chart - result.push(['pie']); - }); - return result; - }; - - // Returns onMouseOver, onMouseOut, and onClick events for the interactive legend - this.getEvents = () => getInteractiveLegendEvents({ - chartNames: this.getChartNames(), - isHidden: this.isHidden, - legendName: 'legend', - onLegendClick: this.handleLegendClick - }); - - // Returns legend data styled per hiddenSeries - this.getLegendData = () => { - const { hiddenSeries } = this.state; - return this.series.map((s, index) => { - return { - ...s.legendItem, // name property - ...getInteractiveLegendItemStyles(hiddenSeries.has(index)) // hidden styles - }; - }); - }; - - // Hide each data series individually - this.handleLegendClick = (props) => { - if (!this.state.hiddenSeries.delete(props.index)) { - this.state.hiddenSeries.add(props.index); - } - this.setState({ hiddenSeries: new Set(this.state.hiddenSeries) }); - }; - - // Returns true if data series is hidden - this.isHidden = (index) => { - const { hiddenSeries } = this.state; // Skip if already hidden - return hiddenSeries.has(index); - }; - - this.isDataAvailable = () => { - const { hiddenSeries } = this.state; - return hiddenSeries.size !== this.series.length; - }; - }; - - render() { - const { hiddenSeries, width } = this.state; - - const data = []; - this.series.map((s, index) => { - data.push(!hiddenSeries.has(index) ? s.datapoints : [{ y: null}]); - }); - - return ( -
    - `${datum.x}: ${datum.y}`} - legendComponent={} - legendPosition="bottom" - padding={{ - bottom: 65, - left: 20, - right: 20, - top: 20 - }} - showAxis={false} - themeColor={ChartThemeColor.multiUnordered} - width={300} - > - - -
    - ); - } -} -``` - -### Legend tooltips - -This demonstrates an approach for applying tooltips to a legend using a custom label component. These tooltips are keyboard navigable. - -```js -import React from 'react'; -import { ChartLabel, ChartLegend, ChartPie, ChartThemeColor } from '@patternfly/react-charts'; -import { Tooltip } from '@patternfly/react-core'; - -class TooltipPieChart extends React.Component { - constructor(props) { - super(props); - - // Custom legend label compoenent - this.LegendLabel = ({datum, ...rest}) => ( - - - - ); - - // Custom legend component - this.getLegend = (legendData) => ( - } - /> - ); - } - - render() { - return ( -
    - `${datum.x}: ${datum.y}`} - legendComponent={this.getLegend([ - { name: 'Cats: 35' }, - { name: 'Dogs: 55' }, - { name: 'Birds: 10' } - ])} - legendPosition="bottom" - padding={{ - bottom: 65, - left: 20, - right: 20, - top: 20 - }} - themeColor={ChartThemeColor.multiOrdered} - width={300} - /> -
    - ); - } -} -``` - -### Legend links - -This demonstrates an approach for applying links to a legend using a custom label component. These links are keyboard navigable. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLabel, ChartLegend, ChartLine, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; -import { Tooltip } from '@patternfly/react-core'; - -class LegendLinkPieChart extends React.Component { - constructor(props) { - super(props); - - // Custom legend label compoenent - this.LegendLabel = ({datum, ...rest}) => ( - - - - ); - - // Custom legend component - this.getLegend = (legendData) => ( - } - /> - ); - } - - render() { - return ( -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendComponent={this.getLegend([ - { name: 'Cats' }, - { name: 'Dogs' }, - { name: 'Birds' }, - { name: 'Mice'} - ])} - legendData={[{ name: 'Cats' }, { name: 'Dogs', symbol: { type: 'dash' } }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - width={450} - > - - - - - - - - - -
    - ); - } -} -``` - -### Legend layout - -This demonstrates an approach for applying a different legend layout and styles using a custom label component. - -```js -import React from 'react'; -import { ChartLabel, ChartLegend, ChartDonut, ChartThemeColor } from '@patternfly/react-charts'; -import { Tooltip } from '@patternfly/react-core'; - -class LegendLayoutPieChart extends React.Component { - constructor(props) { - super(props); - - // Custom legend label compoenent - this.LegendLabel = ({values, ...rest}) => ( - - ); - - // Custom legend component - this.getLegend = (legendData, values) => ( - } - rowGutter={20} - /> - ); - } - - render() { - return ( -
    - `${datum.x}: ${datum.y}`} - legendComponent={this.getLegend([ - { name: 'Cats' }, - { name: 'Dogs' }, - { name: 'Birds' } - ], [ 35, 55, 10 ])} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 140, // Adjusted to accommodate legend - top: 20 - }} - subTitle="Pets" - title="100" - themeColor={ChartThemeColor.multiOrdered} - width={350} - /> -
    - ); - } -} -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- `ChartLegend` may be used as a standalone component, instead of using `legendData` - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `ChartLegend` props, see [VictoryLegend](https://formidable.com/open-source/victory/docs/victory-legend) diff --git a/packages/react-charts/src/components/ChartLegend/index.ts b/packages/react-charts/src/components/ChartLegend/index.ts deleted file mode 100644 index 4af3de066d9..00000000000 --- a/packages/react-charts/src/components/ChartLegend/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartLegend'; diff --git a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.test.tsx b/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.test.tsx deleted file mode 100644 index 23c76e18d35..00000000000 --- a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.test.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Chart } from '../Chart'; -import { ChartAxis } from '../ChartAxis'; -import { ChartGroup } from '../ChartGroup'; -import { ChartLine } from '../ChartLine'; -import { ChartThemeColor } from '../ChartTheme'; -import { createContainer } from '../ChartUtils'; -import { ChartLegendTooltip } from './ChartLegendTooltip'; - -Object.values([true, false]).forEach(() => { - test('ChartLegendTooltip', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('allows tooltip via container component', () => { - const CursorVoronoiContainer = createContainer('cursor', 'voronoi'); - const legendData = [ - { name: 'Cats' }, - { name: 'Dogs', symbol: { type: 'dash' } }, - { name: 'Birds' }, - { name: 'Mice' } - ]; - const view = shallow( - `${datum.y !== null ? datum.y : 'no data'}`} - labelComponent={ datum.x} />} - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - } - legendData={legendData} - legendPosition="bottom" - height={275} - maxDomain={{ y: 10 }} - minDomain={{ y: 0 }} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.green} - width={450} - > - - - - - - - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipContent.test.tsx b/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipContent.test.tsx deleted file mode 100644 index b5b6cff0f07..00000000000 --- a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipContent.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartLegendTooltipContent } from './ChartLegendTooltipContent'; - -Object.values([true, false]).forEach(() => { - test('ChartLegendTooltipContent', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component text', () => { - const legendData = [ - { name: 'Cats' }, - { name: 'Dogs', symbol: { type: 'dash' } }, - { name: 'Birds' }, - { name: 'Mice' } - ]; - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipLabel.test.tsx b/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipLabel.test.tsx deleted file mode 100644 index 8f9fe5af92c..00000000000 --- a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipLabel.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartLegendTooltipLabel } from './ChartLegendTooltipLabel'; - -Object.values([true, false]).forEach(() => { - test('ChartLegendTooltipLabel', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component text', () => { - const legendData = [ - { name: 'Cats' }, - { name: 'Dogs', symbol: { type: 'dash' } }, - { name: 'Birds' }, - { name: 'Mice' } - ]; - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltip.test.tsx.snap b/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltip.test.tsx.snap deleted file mode 100644 index 0ee1d8b012a..00000000000 --- a/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltip.test.tsx.snap +++ /dev/null @@ -1,3895 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartLegendTooltip 1`] = `""`; - -exports[`ChartLegendTooltip 2`] = `""`; - -exports[`allows tooltip via container component 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - cursorDimension="x" - cursorLabelComponent={ - - } - cursorLabelOffset={ - Object { - "x": 5, - "y": -10, - } - } - desc="Average number of pets" - labelComponent={ - - } - labels={[Function]} - mouseFollowTooltips={true} - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#4cb140", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#4cb140", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#4cb140", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - voronoiDimension="x" - voronoiPadding={50} - /> - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - groupComponent={} - height={275} - maxDomain={ - Object { - "y": 10, - } - } - minDomain={ - Object { - "y": 0, - } - } - padding={ - Object { - "bottom": 75, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#4cb140", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#4cb140", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#4cb140", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#4cb140", - "#bde2b9", - "#23511e", - "#7cc674", - "#38812f", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={450} -> - - - - - - - - - - -`; diff --git a/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipContent.test.tsx.snap b/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipContent.test.tsx.snap deleted file mode 100644 index 0758784f0b6..00000000000 --- a/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipContent.test.tsx.snap +++ /dev/null @@ -1,1486 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartLegendTooltipContent 1`] = ` - - - - } - orientation="vertical" - padding={0} - rowGutter={0} - standalone={false} - style={ - Object { - "labels": Object { - "fill": "#f0f0f0", - "lineHeight": 0.275, - "padding": 0, - }, - "title": Object { - "fill": "#f0f0f0", - "padding": 0, - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - x={NaN} - y={NaN} - /> - -`; - -exports[`ChartLegendTooltipContent 2`] = ` - - - - } - orientation="vertical" - padding={0} - rowGutter={0} - standalone={false} - style={ - Object { - "labels": Object { - "fill": "#f0f0f0", - "lineHeight": 0.275, - "padding": 0, - }, - "title": Object { - "fill": "#f0f0f0", - "padding": 0, - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - x={NaN} - y={NaN} - /> - -`; - -exports[`renders component text 1`] = ` - - - - } - orientation="vertical" - padding={0} - rowGutter={0} - standalone={false} - style={ - Object { - "labels": Object { - "fill": "#f0f0f0", - "lineHeight": 0.275, - "padding": 0, - }, - "title": Object { - "fill": "#f0f0f0", - "padding": 0, - }, - } - } - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - x={NaN} - y={NaN} - /> - -`; diff --git a/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipLabel.test.tsx.snap b/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipLabel.test.tsx.snap deleted file mode 100644 index 7a2d393dba4..00000000000 --- a/packages/react-charts/src/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipLabel.test.tsx.snap +++ /dev/null @@ -1,73 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartLegendTooltipLabel 1`] = ` - - - - -`; - -exports[`ChartLegendTooltipLabel 2`] = ` - - - - -`; - -exports[`renders component text 1`] = ` - - - - -`; diff --git a/packages/react-charts/src/components/ChartLegendTooltip/index.ts b/packages/react-charts/src/components/ChartLegendTooltip/index.ts deleted file mode 100644 index c50031b7eb9..00000000000 --- a/packages/react-charts/src/components/ChartLegendTooltip/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './ChartLegendTooltip'; -export * from './ChartLegendTooltipContent'; -export * from './ChartLegendTooltipLabel'; diff --git a/packages/react-charts/src/components/ChartLine/__snapshots__/ChartLine.test.tsx.snap b/packages/react-charts/src/components/ChartLine/__snapshots__/ChartLine.test.tsx.snap deleted file mode 100644 index 45ce7e0830a..00000000000 --- a/packages/react-charts/src/components/ChartLine/__snapshots__/ChartLine.test.tsx.snap +++ /dev/null @@ -1,5191 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartLine 1`] = ` - - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - } - clipPathComponent={} - groupComponent={} - rectComponent={} - /> - } - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - renderInPortal={true} - textComponent={} - tspanComponent={} - /> - } - samples={50} - sortKey="x" - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartLine 2`] = ` - - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - } - clipPathComponent={} - groupComponent={} - rectComponent={} - /> - } - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - renderInPortal={true} - textComponent={} - tspanComponent={} - /> - } - samples={50} - sortKey="x" - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders component data 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - groupComponent={} - height={200} - minDomain={ - Object { - "y": 0, - } - } - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - - - - - -`; diff --git a/packages/react-charts/src/components/ChartLine/examples/ChartLine.md b/packages/react-charts/src/components/ChartLine/examples/ChartLine.md deleted file mode 100644 index 5fe358ddfc1..00000000000 --- a/packages/react-charts/src/components/ChartLine/examples/ChartLine.md +++ /dev/null @@ -1,314 +0,0 @@ ---- -id: Line chart -section: charts -propComponents: [ - 'Chart', - 'ChartAxis', - 'ChartGroup', - 'ChartLine', - 'ChartVoronoiContainer' -] -hideDarkMode: true ---- - -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, ChartLegendTooltip, ChartThemeVariant, ChartVoronoiContainer, createContainer, getResizeObserver } from '@patternfly/react-charts'; -import { VictoryZoomContainer } from 'victory-zoom-container'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a line chart using a Katacoda tutorial starting with a simple chart, adding multiple datasets, tooltips, axis labels, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/line-chart) - -## Examples -### Basic with right aligned legend -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendData={[{ name: 'Cats' }, { name: 'Dogs', symbol: { type: 'dash' } }, { name: 'Birds' }, { name: 'Mice' }]} - legendOrientation="vertical" - legendPosition="right" - height={250} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - width={600} - > - - - - - - - - - -
    -``` - -### Green with bottom aligned legend - -This demonstrates how to combine cursor and voronoi containers to display tooltips along with a cursor. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, ChartLegendTooltip, ChartVoronoiContainer, createContainer } from '@patternfly/react-charts'; - -class BottomAlignedLegend extends React.Component { - render() { - // Note: Container order is important - const CursorVoronoiContainer = createContainer("voronoi", "cursor"); - const legendData = [{ childName: 'cats', name: 'Cats' }, { childName: 'dogs', name: 'Dogs', symbol: { type: 'dash' }}, { childName: 'birds', name: 'Birds' }, { childName: 'mice', name: 'Mice' }]; - - return ( -
    - `${datum.y}`} - labelComponent={ datum.x}/>} - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - } - legendData={legendData} - legendPosition="bottom" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.green} - width={450} - > - - - - - - - - - -
    - ); - } -} -``` - -### Multi-color (unordered) with responsive container - -This demonstrates zoom for the x axis only. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, getResizeObserver } from '@patternfly/react-charts'; -import { VictoryZoomContainer } from 'victory-zoom-container'; - -class MultiColorChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if (this.containerRef.current && this.containerRef.current.clientWidth) { - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - - return ( -
    -
    - } - legendData={[{ name: 'Cats' }, { name: 'Dogs', symbol: { type: 'dash' } }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom-left" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.multiUnordered} - width={width} - > - - - - - - - - - -
    -
    - ); - } -} -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` -- The `theme` and `themeColor` props should be applied at the most top level component -- Use `ChartGroup` to apply theme color scales and other properties to multiple components - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) - - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) - - For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) - - For `ChartLine` props, see [Victoryline](https://formidable.com/open-source/victory/docs/victory-line) - - For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) - - For `VictoryZoomContainer` props, see [VictoryZoomContainerline](https://formidable.com/open-source/victory/docs/victory-zoom-container) diff --git a/packages/react-charts/src/components/ChartLine/index.ts b/packages/react-charts/src/components/ChartLine/index.ts deleted file mode 100644 index fe8b0c733b8..00000000000 --- a/packages/react-charts/src/components/ChartLine/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartLine'; diff --git a/packages/react-charts/src/components/ChartPie/ChartPie.test.tsx b/packages/react-charts/src/components/ChartPie/ChartPie.test.tsx deleted file mode 100644 index 48c8a278583..00000000000 --- a/packages/react-charts/src/components/ChartPie/ChartPie.test.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartPie } from './ChartPie'; - -Object.values([true, false]).forEach(() => { - test('ChartPie', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartPie/ChartPie.tsx b/packages/react-charts/src/components/ChartPie/ChartPie.tsx deleted file mode 100644 index b3278297464..00000000000 --- a/packages/react-charts/src/components/ChartPie/ChartPie.tsx +++ /dev/null @@ -1,576 +0,0 @@ -import * as React from 'react'; -import hoistNonReactStatics from 'hoist-non-react-statics'; -import { - AnimatePropTypeInterface, - CategoryPropType, - DataGetterPropType, - EventCallbackInterface, - EventPropTypeInterface, - Helpers, - NumberOrCallback, - OriginType, - PaddingProps, - SliceNumberOrCallback, - SortOrderPropType, - StringOrNumberOrCallback, - StringOrNumberOrList, - VictoryStyleInterface -} from 'victory-core'; -import { - SliceProps, - VictoryPie, - VictoryPieProps, - VictorySliceLabelPositionType, - VictorySliceTTargetType -} from 'victory-pie'; -import { ChartContainer } from '../ChartContainer'; -import { ChartLegend, ChartLegendOrientation } from '../ChartLegend'; -import { ChartCommonStyles, ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; -import { getComputedLegend, getPaddingForSide, getTheme } from '../ChartUtils'; - -export enum ChartPieLabelPosition { - centroid = 'centroid', - endAngle = 'endAngle', - startAngle = 'startAngle' -} - -export enum ChartPieLegendPosition { - bottom = 'bottom', - right = 'right' -} - -export enum ChartPieSortOrder { - ascending = 'ascending', - descending = 'descending' -} - -/** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-pie/src/index.d.ts - */ -export interface ChartPieProps extends VictoryPieProps { - /** - * Specifies the tooltip capability of the container component. A value of true allows the chart to add a - * ChartTooltip component to the labelComponent property. This is a shortcut to display tooltips when the labels - * property is also provided. - */ - allowTooltip?: boolean; - /** - * The animate prop specifies props for VictoryAnimation to use. - * The animate prop should also be used to specify enter and exit - * transition configurations with the `onExit` and `onEnter` namespaces respectively. - * - * @propType boolean | object - * @example - * {duration: 500, onExit: () => {}, onEnter: {duration: 500, before: () => ({y: 0})})} - */ - animate?: boolean | AnimatePropTypeInterface; - /** - * The ariaDesc prop specifies the description of the chart/SVG to assist with - * accessibility for screen readers. - * - * Note: Overridden by the desc prop of containerComponent - */ - ariaDesc?: string; - /** - * The ariaTitle prop specifies the title to be applied to the SVG to assist - * accessibility for screen readers. - * - * Note: Overridden by the title prop of containerComponent - */ - ariaTitle?: string; - /** - * The categories prop specifies how categorical data for a chart should be ordered. - * This prop should be given as an array of string values, or an object with - * these arrays of values specified for x and y. If this prop is not set, - * categorical data will be plotted in the order it was given in the data array - * - * @propType string[] | { x: string[], y: string[] } - * @example ["dogs", "cats", "mice"] - */ - categories?: CategoryPropType; - /** - * The colorScale prop is an optional prop that defines the color scale the pie - * will be created on. This prop should be given as an array of CSS colors, or as a string - * corresponding to one of the built in color scales. ChartPie will automatically assign - * values from this color scale to the pie slices unless colors are explicitly provided in the - * data object - */ - colorScale?: string[]; - /** - * The constrainToVisibleArea prop determines whether to coerce tooltips so that they fit within the visible area of - * the chart. When this prop is set to true, tooltip pointers will still point to the correct data point, but the - * center of the tooltip will be shifted to fit within the overall width and height of the svg Victory renders. - */ - constrainToVisibleArea?: boolean; - /** - * The containerComponent prop takes an entire component which will be used to - * create a container element for standalone charts. - * The new element created from the passed containerComponent wil be provided with - * these props from ChartPie: height, width, children - * (the chart itself) and style. Props that are not provided by the - * child chart component include title and desc, both of which - * are intended to add accessibility to Victory components. The more descriptive these props - * are, the more accessible your data will be for people using screen readers. - * Any of these props may be overridden by passing in props to the supplied component, - * or modified or ignored within the custom component itself. If a dataComponent is - * not provided, ChartPie will use the default ChartContainer component. - * - * @example - */ - containerComponent?: React.ReactElement; - /** - * Set the cornerRadius for every dataComponent (Slice by default) within ChartPie - * - * @propType number | Function - */ - cornerRadius?: SliceNumberOrCallback; - /** - * The data prop specifies the data to be plotted, - * where data X-value is the slice label (string or number), - * and Y-value is the corresponding number value represented by the slice - * Data should be in the form of an array of data points. - * Each data point may be any format you wish (depending on the `x` and `y` accessor props), - * but by default, an object with x and y properties is expected. - * - * @example [{x: 1, y: 2}, {x: 2, y: 3}], [[1, 2], [2, 3]], - * [[{x: "a", y: 1}, {x: "b", y: 2}], [{x: "a", y: 2}, {x: "b", y: 3}]] - */ - data?: any[]; - /** - * The dataComponent prop takes an entire, HTML-complete data component which will be used to - * create slices for each datum in the pie chart. The new element created from the passed - * dataComponent will have the property datum set by the pie chart for the point it renders; - * properties style and pathFunction calculated by ChartPie; an index property set - * corresponding to the location of the datum in the data provided to the pie; events bound to - * the ChartPie; and the d3 compatible slice object. - * If a dataComponent is not provided, ChartPie's Slice component will be used. - */ - dataComponent?: React.ReactElement; - /** - * The overall end angle of the pie in degrees. This prop is used in conjunction with - * startAngle to create a pie that spans only a segment of a circle. - */ - endAngle?: number; - /** - * Similar to data accessor props `x` and `y`, this prop may be used to functionally - * assign eventKeys to data - * - * @propType number | string | Function - */ - eventKey?: StringOrNumberOrCallback; - /** - * The event prop takes an array of event objects. Event objects are composed of - * a target, an eventKey, and eventHandlers. Targets may be any valid style namespace - * for a given component, so "data" and "labels" are all valid targets for ChartPie - * events. The eventKey may optionally be used to select a single element by index rather than - * an entire set. The eventHandlers object should be given as an object whose keys are standard - * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given - * as an object or an array of objects with optional target and eventKey keys, - * and a mutation key whose value is a function. The target and eventKey keys - * will default to those corresponding to the element the event handler was attached to. - * The mutation function will be called with the calculated props for the individual selected - * element (i.e. a single bar), and the object returned from the mutation function - * will override the props of the selected element via object assignment. - * - * @propType object[] - * @example - * events={[ - * { - * target: "data", - * eventKey: 1, - * eventHandlers: { - * onClick: () => { - * return [ - * { - * eventKey: 2, - * mutation: (props) => { - * return {style: merge({}, props.style, {fill: "orange"})}; - * } - * }, { - * eventKey: 2, - * target: "labels", - * mutation: () => { - * return {text: "hey"}; - * } - * } - * ]; - * } - * } - * } - * ]} - */ - events?: EventPropTypeInterface[]; - /** - * ChartPie uses the standard externalEventMutations prop. - * - * @propType object[] - */ - externalEventMutations?: EventCallbackInterface[]; - /** - * The groupComponent prop takes an entire component which will be used to - * create group elements for use within container elements. This prop defaults - * to a tag on web, and a react-native-svg tag on mobile - */ - groupComponent?: React.ReactElement; - /** - * Specifies the height the svg viewBox of the chart container. This value should be given as a - * number of pixels. - * - * Because Victory renders responsive containers, the width and height props do not determine the width and - * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of - * pixels will depend on the size of the container the chart is rendered into. - * - * Note: When adding a legend, height (the overall SVG height) may need to be larger than pieHeight (the pie size) - * in order to accommodate the extra legend. - * - * By default, pieHeight is the min. of either height or width. This covers most use cases in order to accommodate - * legends within the same SVG. However, pieHeight (not height) may need to be set in order to adjust the pie height. - * - * Typically, the parent container is set to the same width in order to maintain the aspect ratio. - */ - height?: number; - /** - * When creating a donut chart, this prop determines the number of pixels between - * the center of the chart and the inner edge. When this prop is set to zero - * a regular pie chart is rendered. - * - * @propType number | Function - */ - innerRadius?: NumberOrCallback; - /** - * The labelComponent prop takes in an entire label component which will be used - * to create a label for the area. The new element created from the passed labelComponent - * will be supplied with the following properties: x, y, index, data, verticalAnchor, - * textAnchor, angle, style, text, and events. any of these props may be overridden - * by passing in props to the supplied component, or modified or ignored within - * the custom component itself. If labelComponent is omitted, a new ChartLabel - * will be created with props described above. This labelComponent prop should be used to - * provide a series label for ChartPie. If individual labels are required for each - * data point, they should be created by composing ChartPie with VictoryScatter - */ - labelComponent?: React.ReactElement; - /** - * The labelPosition prop specifies the angular position of each label relative to its corresponding slice. - * This prop should be given as "startAngle", "endAngle", "centroid", or as a function that returns one of these - * values. When this prop is not given, the label will be positioned at the centroid of each slice. - * - * @propType string | Function - */ - labelPosition?: VictorySliceLabelPositionType | ((props: SliceProps) => VictorySliceLabelPositionType); - /** - * The labelRadius prop defines the radius of the arc that will be used for positioning each slice label. - * If this prop is not set, the label radius will default to the radius of the pie + label padding. - * - * @propType number | Function - */ - labelRadius?: number | ((props: SliceProps) => number); - /** - * The labels prop defines labels that will appear above each bar in your chart. - * This prop should be given as an array of values or as a function of data. - * If given as an array, the number of elements in the array should be equal to - * the length of the data array. Labels may also be added directly to the data object - * like data={[{x: 1, y: 1, label: "first"}]}. - * - * @example ["spring", "summer", "fall", "winter"], (datum) => datum.title - */ - labels?: string[] | number[] | ((data: any) => string | number | null); - /** - * Allows legend items to wrap. A value of true allows the legend to wrap onto the next line - * if its container is not wide enough. - * - * Note: This is overridden by the legendItemsPerRow property - */ - legendAllowWrap?: boolean; - /** - * The legend component to render with chart. - * - * Note: Use legendData so the legend width can be calculated and positioned properly. - * Default legend properties may be applied - */ - legendComponent?: React.ReactElement; - /** - * Specify data via the data prop. ChartLegend expects data as an - * array of objects with name (required), symbol, and labels properties. - * The data prop must be given as an array. - * - * @example legendData={[{ name: `GBps capacity - 45%` }, { name: 'Unused' }]} - */ - legendData?: { - name?: string; - symbol?: { - fill?: string; - type?: string; - }; - }[]; - /** - * The orientation prop takes a string that defines whether legend data - * are displayed in a row or column. When orientation is "horizontal", - * legend items will be displayed in a single row. When orientation is - * "vertical", legend items will be displayed in a single column. Line - * and text-wrapping is not currently supported, so "vertical" - * orientation is both the default setting and recommended for - * displaying many series of data. - */ - legendOrientation?: 'horizontal' | 'vertical'; - /** - * The legend position relation to the pie chart. Valid values are 'bottom' and 'right' - * - * Note: When adding a legend, padding may need to be adjusted in order to accommodate the extra legend. In some - * cases, the legend may not be visible until enough padding is applied. - */ - legendPosition?: 'bottom' | 'right'; - /** - * The name prop is used to reference a component instance when defining shared events. - */ - name?: string; - /** - * Victory components will pass an origin prop is to define the center point in svg coordinates for polar charts. - * - * Note: It will not typically be necessary to set an origin prop manually - * - * @propType { x: number, y: number } - */ - origin?: OriginType; - /** - * The padAngle prop determines the amount of separation between adjacent data slices - * in number of degrees - * - * @propType number | Function - */ - padAngle?: NumberOrCallback; - /** - * The padding props specifies the amount of padding in number of pixels between - * the edge of the chart and any rendered child components. This prop can be given - * as a number or as an object with padding specified for top, bottom, left - * and right. - * - * @propType number | { top: number, bottom: number, left: number, right: number } - */ - padding?: PaddingProps; - /** - * Specifies the radius of the chart. If this property is not provided it is computed - * from width, height, and padding props - * - * @propType number | Function - */ - radius?: NumberOrCallback; - /** - * The sharedEvents prop is used internally to coordinate events between components. - * - * Note: This prop should not be set manually. - * - * @hide - */ - sharedEvents?: { events: any[]; getEventState: Function }; - /** - * Use the sortKey prop to indicate how data should be sorted. This prop - * is given directly to the lodash sortBy function to be executed on the final dataset. - * - * @propType number | string | Function | string[] - */ - sortKey?: DataGetterPropType; - /** - * The sortOrder prop specifies whether sorted data should be returned in 'ascending' or 'descending' order. - * - * @propType string - */ - sortOrder?: SortOrderPropType; - /** - * The standalone prop determines whether the component will render a standalone svg - * or a tag that will be included in an external svg. Set standalone to false to - * compose ChartPie with other components within an enclosing tag. - */ - standalone?: boolean; - /** - * The overall start angle of the pie in degrees. This prop is used in conjunction with - * endAngle to create a pie that spans only a segment of a circle. - */ - startAngle?: number; - /** - * The style prop specifies styles for your pie. ChartPie relies on Radium, - * so valid Radium style objects should work for this prop. Height, width, and - * padding should be specified via the height, width, and padding props. - * - * @propType { parent: object, data: object, labels: object } - * @example {data: {stroke: "black"}, label: {fontSize: 10}} - */ - style?: VictoryStyleInterface; - /** - * The theme prop takes a style object with nested data, labels, and parent objects. - * You can create this object yourself, or you can use a theme provided by - * When using ChartPie as a solo component, implement the theme directly on - * ChartPie. If you are wrapping ChartPie in ChartChart or ChartGroup, - * please call the theme on the outermost wrapper component instead. - * - * @propType object - */ - theme?: ChartThemeDefinition; - /** - * Specifies the theme color. Valid values are 'blue', 'green', 'multi', etc. - * - * Note: Not compatible with theme prop - * - * @example themeColor={ChartThemeColor.blue} - */ - themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; - /** - * Specifies the width of the svg viewBox of the chart container. This value should be given as a number of pixels. - * - * Because Victory renders responsive containers, the width and height props do not determine the width and - * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of - * pixels will depend on the size of the container the chart is rendered into. Typically, the parent container is set - * to the same width in order to maintain the aspect ratio. - */ - width?: number; - /** - * The x prop specifies how to access the X value of each data point. - * If given as a function, it will be run on each data point, and returned value will be used. - * If given as an integer, it will be used as an array index for array-type data points. - * If given as a string, it will be used as a property key for object-type data points. - * If given as an array of strings, or a string containing dots or brackets, - * it will be used as a nested object property path (for details see Lodash docs for _.get). - * If `null` or `undefined`, the data value will be used as is (identity function/pass-through). - * - * @propType number | string | Function | string[] - * @example 0, 'x', 'x.value.nested.1.thing', 'x[2].also.nested', null, d => Math.sin(d) - */ - x?: DataGetterPropType; - /** - * The y prop specifies how to access the Y value of each data point. - * If given as a function, it will be run on each data point, and returned value will be used. - * If given as an integer, it will be used as an array index for array-type data points. - * If given as a string, it will be used as a property key for object-type data points. - * If given as an array of strings, or a string containing dots or brackets, - * it will be used as a nested object property path (for details see Lodash docs for _.get). - * If `null` or `undefined`, the data value will be used as is (identity function/pass-through). - * - * @propType number | string | Function | string[] - * @example 0, 'y', 'y.value.nested.1.thing', 'y[2].also.nested', null, d => Math.sin(d) - */ - y?: DataGetterPropType; -} - -export const ChartPie: React.FunctionComponent = ({ - allowTooltip = true, - ariaDesc, - ariaTitle, - constrainToVisibleArea = false, - containerComponent = , - labels, - legendAllowWrap = false, - legendComponent = , - legendData, - legendPosition = ChartCommonStyles.legend.position as ChartPieLegendPosition, - padding, - radius, - standalone = true, - themeColor, - themeVariant, - - // destructure last - theme = getTheme(themeColor, themeVariant), - labelComponent = allowTooltip ? ( - - ) : ( - undefined - ), - legendOrientation = theme.legend.orientation as ChartLegendOrientation, - height = theme.pie.height, - width = theme.pie.width, - ...rest -}: ChartPieProps) => { - const defaultPadding = { - bottom: getPaddingForSide('bottom', padding, theme.pie.padding), - left: getPaddingForSide('left', padding, theme.pie.padding), - right: getPaddingForSide('right', padding, theme.pie.padding), - top: getPaddingForSide('top', padding, theme.pie.padding) - }; - // Ensure non-negative value is returned - const getDefaultRadius = () => { - const result = Helpers.getRadius({ - height, - width, - padding: defaultPadding - }); - return result > -1 ? result : undefined; - }; - const chartRadius = radius ? radius : getDefaultRadius(); - - const chart = ( - - ); - - const legend = React.cloneElement(legendComponent, { - data: legendData, - key: 'pf-chart-pie-legend', - orientation: legendOrientation, - theme, - ...legendComponent.props - }); - - // Returns a computed legend - const getLegend = () => { - if (!legend.props.data) { - return null; - } - return getComputedLegend({ - allowWrap: legendAllowWrap, - chartType: 'pie', - height, - legendComponent: legend, - padding: defaultPadding, - position: legendPosition, - theme, - width - }); - }; - - // Clone so users can override container props - const container = React.cloneElement( - containerComponent, - { - desc: ariaDesc, - height, - title: ariaTitle, - width, - theme, - ...containerComponent.props - }, - [chart, getLegend()] - ); - - return standalone ? ( - {container} - ) : ( - - {chart} - {getLegend()} - - ); -}; -ChartPie.displayName = 'ChartPie'; - -// Note: VictoryPie.role must be hoisted -hoistNonReactStatics(ChartPie, VictoryPie); diff --git a/packages/react-charts/src/components/ChartPie/__snapshots__/ChartPie.test.tsx.snap b/packages/react-charts/src/components/ChartPie/__snapshots__/ChartPie.test.tsx.snap deleted file mode 100644 index 8d52b491bf0..00000000000 --- a/packages/react-charts/src/components/ChartPie/__snapshots__/ChartPie.test.tsx.snap +++ /dev/null @@ -1,4226 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartPie 1`] = ` - - - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - data={ - Array [ - Object { - "x": "A", - "y": 1, - }, - Object { - "x": "B", - "y": 2, - }, - Object { - "x": "C", - "y": 3, - }, - Object { - "x": "D", - "y": 1, - }, - Object { - "x": "E", - "y": 2, - }, - ] - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - height={230} - key="pf-chart-pie" - labelComponent={ - - } - radius={95} - sortOrder="ascending" - standalone={false} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={230} - /> - - -`; - -exports[`ChartPie 2`] = ` - - - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - data={ - Array [ - Object { - "x": "A", - "y": 1, - }, - Object { - "x": "B", - "y": 2, - }, - Object { - "x": "C", - "y": 3, - }, - Object { - "x": "D", - "y": 1, - }, - Object { - "x": "E", - "y": 2, - }, - ] - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - height={230} - key="pf-chart-pie" - labelComponent={ - - } - radius={95} - sortOrder="ascending" - standalone={false} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={230} - /> - - -`; - -exports[`renders component data 1`] = ` - - - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - data={ - Array [ - Object { - "x": "Cats", - "y": 35, - }, - Object { - "x": "Dogs", - "y": 55, - }, - Object { - "x": "Birds", - "y": 10, - }, - ] - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - height={200} - key="pf-chart-pie" - labelComponent={ - - } - radius={80} - sortOrder="ascending" - standalone={false} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} - /> - - -`; diff --git a/packages/react-charts/src/components/ChartPie/examples/ChartPie.md b/packages/react-charts/src/components/ChartPie/examples/ChartPie.md deleted file mode 100644 index d71bd2a01f8..00000000000 --- a/packages/react-charts/src/components/ChartPie/examples/ChartPie.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -id: Pie chart -section: charts -propComponents: ['ChartPie'] -hideDarkMode: true ---- - -import { ChartPie, ChartThemeColor, ChartThemeVariant } from '@patternfly/react-charts'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a pie chart using a Katacoda tutorial starting with a simple chart, adding tooltips, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/pie-chart) - -## Examples -### Basic with right aligned legend -```js -import React from 'react'; -import { ChartPie } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 140, // Adjusted to accommodate legend - top: 20 - }} - width={350} - /> -
    -``` - -### Orange with right aligned legend -```js -import React from 'react'; -import { ChartPie, ChartThemeColor } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 140, // Adjusted to accommodate legend - top: 20 - }} - themeColor={ChartThemeColor.orange} - width={350} - /> -
    -``` - -### Multi-color (ordered) with bottom aligned legend -```js -import React from 'react'; -import { ChartPie, ChartThemeColor } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendPosition="bottom" - padding={{ - bottom: 65, - left: 20, - right: 20, - top: 20 - }} - themeColor={ChartThemeColor.multiOrdered} - width={300} - /> -
    -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `ChartPie` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) diff --git a/packages/react-charts/src/components/ChartPie/index.ts b/packages/react-charts/src/components/ChartPie/index.ts deleted file mode 100644 index 75d7ee64430..00000000000 --- a/packages/react-charts/src/components/ChartPie/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartPie'; diff --git a/packages/react-charts/src/components/ChartPoint/ChartPoint.test.tsx b/packages/react-charts/src/components/ChartPoint/ChartPoint.test.tsx deleted file mode 100644 index 467b4d32607..00000000000 --- a/packages/react-charts/src/components/ChartPoint/ChartPoint.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartLegend } from '../ChartLegend'; -import { ChartPoint } from './ChartPoint'; - -Object.values([true, false]).forEach(() => { - test('ChartPoint', () => { - const view = shallow(} />); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartPoint/__snapshots__/ChartPoint.test.tsx.snap b/packages/react-charts/src/components/ChartPoint/__snapshots__/ChartPoint.test.tsx.snap deleted file mode 100644 index 1b32cf51027..00000000000 --- a/packages/react-charts/src/components/ChartPoint/__snapshots__/ChartPoint.test.tsx.snap +++ /dev/null @@ -1,2797 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartPoint 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - data={ - Array [ - Object { - "name": "Series 1", - }, - Object { - "name": "Series 2", - }, - ] - } - dataComponent={} - groupComponent={} - labelComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - titleComponent={} -/> -`; - -exports[`ChartPoint 2`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - data={ - Array [ - Object { - "name": "Series 1", - }, - Object { - "name": "Series 2", - }, - ] - } - dataComponent={} - groupComponent={} - labelComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - titleComponent={} -/> -`; - -exports[`renders component data 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - data={ - Array [ - Object { - "name": "Cats", - }, - Object { - "name": "Dogs", - "symbol": Object { - "type": "dash", - }, - }, - ] - } - dataComponent={} - groupComponent={} - height={50} - labelComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - title="Average number of pets" - titleComponent={} - width={200} -/> -`; diff --git a/packages/react-charts/src/components/ChartPoint/index.ts b/packages/react-charts/src/components/ChartPoint/index.ts deleted file mode 100644 index 614eba5b7ee..00000000000 --- a/packages/react-charts/src/components/ChartPoint/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartPoint'; diff --git a/packages/react-charts/src/components/ChartScatter/__snapshots__/ChartScatter.test.tsx.snap b/packages/react-charts/src/components/ChartScatter/__snapshots__/ChartScatter.test.tsx.snap deleted file mode 100644 index 03944d7d081..00000000000 --- a/packages/react-charts/src/components/ChartScatter/__snapshots__/ChartScatter.test.tsx.snap +++ /dev/null @@ -1,5175 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartScatter 1`] = ` - - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - samples={50} - size={[Function]} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartScatter 2`] = ` - - } - dataComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - samples={50} - size={[Function]} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders component data 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - groupComponent={} - height={200} - minDomain={ - Object { - "y": 0, - } - } - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - - - - - -`; diff --git a/packages/react-charts/src/components/ChartScatter/examples/ChartScatter.md b/packages/react-charts/src/components/ChartScatter/examples/ChartScatter.md deleted file mode 100644 index 1461b20006f..00000000000 --- a/packages/react-charts/src/components/ChartScatter/examples/ChartScatter.md +++ /dev/null @@ -1,301 +0,0 @@ ---- -id: Scatter chart -section: charts -propComponents: [ - 'Chart', - 'ChartArea', - 'ChartAxis', - 'ChartGroup', - 'ChartLine', - 'ChartScatter' -] -hideDarkMode: true ---- - -import { - Chart, - ChartArea, - ChartAxis, - ChartGroup, - ChartLine, - ChartScatter, - ChartThemeColor, - ChartVoronoiContainer, - getResizeObserver -} from '@patternfly/react-charts'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -## Examples -### Area chart - -This demonstrates how to add interactive data points to an area chart. - -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartGroup, ChartScatter, ChartThemeColor, ChartVoronoiContainer, getResizeObserver } from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // For mixed blend mode - -class ScatterAreaChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if (this.containerRef.current && this.containerRef.current.clientWidth) { - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - - this.series = [ - { - datapoints: [ - { name: 'Cats', x: '2015', y: 3 }, - { name: 'Cats', x: '2016', y: 4 }, - { name: 'Cats', x: '2017', y: 8 }, - { name: 'Cats', x: '2018', y: 6 } - ], - legendItem: { name: 'Cats' } - }, - { - datapoints: [ - { name: 'Dogs', x: '2015', y: 2 }, - { name: 'Dogs', x: '2016', y: 3 }, - { name: 'Dogs', x: '2017', y: 4 }, - { name: 'Dogs', x: '2018', y: 5 }, - { name: 'Dogs', x: '2019', y: 6 } - ], - legendItem: { name: 'Dogs' } - }, - { - datapoints: [ - { name: 'Birds', x: '2015', y: 1 }, - { name: 'Birds', x: '2016', y: 2 }, - { name: 'Birds', x: '2017', y: 3 }, - { name: 'Birds', x: '2018', y: 2 }, - { name: 'Birds', x: '2019', y: 4 } - ], - legendItem: { name: 'Birds' } - }]; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - - return ( -
    -
    - datum.childName.includes('area-') ? `${datum.name}: ${datum.y}` : null} - constrainToVisibleArea - /> - } - height={225} - legendData={this.series.map(s => s.legendItem)} - legendPosition="bottom-left" - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50, - }} - maxDomain={{y: 9}} - themeColor={ChartThemeColor.multiUnordered} - width={width} - > - - - - {this.series.map((s, idx) => { - return ( - - ); - })} - - - {this.series.map((s, idx) => { - return ( - - ); - })} - - -
    -
    - ); - } -} -``` - -### Line chart - -This demonstrates how to add interactive data points to a line chart. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartScatter, ChartThemeColor, ChartVoronoiContainer, getResizeObserver } from '@patternfly/react-charts'; - -class ScatterLineChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if (this.containerRef.current && this.containerRef.current.clientWidth) { - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - - this.series = [ - { - datapoints: [ - { name: 'Cats', x: '2015', y: 1 }, - { name: 'Cats', x: '2016', y: 2 }, - { name: 'Cats', x: '2017', y: 5 }, - { name: 'Cats', x: '2018', y: 3 } - ], - legendItem: { name: 'Cats' } - }, - { - datapoints: [ - { name: 'Dogs', x: '2015', y: 2 }, - { name: 'Dogs', x: '2016', y: 1 }, - { name: 'Dogs', x: '2017', y: 7 }, - { name: 'Dogs', x: '2018', y: 4 } - ], - legendItem: { name: 'Dogs' }, - style: { - data: { - strokeDasharray: '3,3' - } - } - }, - { - datapoints: [ - { name: 'Birds', x: '2015', y: 3 }, - { name: 'Birds', x: '2016', y: 4 }, - { name: 'Birds', x: '2017', y: 9 }, - { name: 'Birds', x: '2018', y: 5 } - ], - legendItem: { name: 'Birds' } - }, - { - datapoints: [ - { name: 'Mice', x: '2015', y: 3 }, - { name: 'Mice', x: '2016', y: 3 }, - { name: 'Mice', x: '2017', y: 8 }, - { name: 'Mice', x: '2018', y: 7 } - ], - legendItem: { name: 'Birds' } - }]; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - - return ( -
    -
    - datum.childName.includes('line-') ? `${datum.name}: ${datum.y}` : null} - constrainToVisibleArea - /> - } - legendData={this.series.map(s => s.legendItem)} - legendPosition="bottom-left" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.orange} - width={width} - > - - - - {this.series.map((s, idx) => { - return ( - - ); - })} - - - {this.series.map((s, idx) => { - return ( - - ); - })} - - -
    -
    - ); - } -} -``` - -## Documentation - -- For single data points or zero values, you may want to set the `domain` prop. See Victory's FAQ - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) - - For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) - - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) - - For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) - - For `ChartLine` props, see [VictoryLine](https://formidable.com/open-source/victory/docs/victory-line) - - For `ChartScatter` props, see [VictoryScatter](https://formidable.com/open-source/victory/docs/victory-scatter) diff --git a/packages/react-charts/src/components/ChartScatter/index.ts b/packages/react-charts/src/components/ChartScatter/index.ts deleted file mode 100644 index 153d1211750..00000000000 --- a/packages/react-charts/src/components/ChartScatter/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartScatter'; diff --git a/packages/react-charts/src/components/ChartStack/__snapshots__/ChartStack.test.tsx.snap b/packages/react-charts/src/components/ChartStack/__snapshots__/ChartStack.test.tsx.snap deleted file mode 100644 index 3a35812aab2..00000000000 --- a/packages/react-charts/src/components/ChartStack/__snapshots__/ChartStack.test.tsx.snap +++ /dev/null @@ -1,5140 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartStack 1`] = ` - - } - fillInMissingData={true} - groupComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartStack 2`] = ` - - } - fillInMissingData={true} - groupComponent={} - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`renders component data 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - domainPadding={ - Object { - "x": Array [ - 30, - 25, - ], - } - } - groupComponent={} - height={200} - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={300} -> - - - - - - - -`; diff --git a/packages/react-charts/src/components/ChartStack/examples/ChartStack.md b/packages/react-charts/src/components/ChartStack/examples/ChartStack.md deleted file mode 100644 index b2feca6568d..00000000000 --- a/packages/react-charts/src/components/ChartStack/examples/ChartStack.md +++ /dev/null @@ -1,430 +0,0 @@ ---- -id: Stack chart -section: charts -propComponents: [ - 'Chart', - 'ChartArea', - 'ChartBar', - 'ChartStack', - 'ChartTooltip' -] -hideDarkMode: true ---- - -import { - Chart, - ChartArea, - ChartAxis, - ChartBar, - ChartStack, - ChartLegendTooltip, - ChartThemeColor, - ChartTooltip, - ChartVoronoiContainer, - createContainer, - getResizeObserver -} from '@patternfly/react-charts'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a stack chart using a Katacoda tutorial starting with a simple chart, adding multiple datasets, tooltips, axis labels, a legend, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/stack-chart) - -## Examples -### Basic with right aligned legend -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartStack, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} - legendOrientation="vertical" - legendPosition="right" - height={250} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - width={600} - > - - - - - - - - - -
    -``` - -### Horizontal with bottom aligned legend -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartStack, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom" - height={275} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.gold} - width={450} - > - - - - - - - - - -
    -``` - -### Multi-color (ordered) horizontal with bottom aligned legend - -This demonstrates an alternate way of applying tooltips using data labels. - -```js -import React from 'react'; -import { Chart, ChartBar, ChartAxis, ChartStack, ChartThemeColor, ChartTooltip } from '@patternfly/react-charts'; - -
    - - - - - } - /> - } - /> - } - /> - } - /> - - -
    -``` - -### Monthly data with responsive container -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartStack, ChartTooltip, getResizeObserver } from '@patternfly/react-charts'; - -class MonthlyResponsiveStack extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - - this.handleResize = () => { - if(this.containerRef.current && this.containerRef.current.clientWidth){ - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - - this.bars = []; - for(let i = 1; i < 32; i++){ - this.bars.push({ x: `Aug. ${i}`, y: Math.floor(Math.random() * 6) + 1 }); - }; - - this.renderSocketBars = () => { - let socketBars = this.bars.map((tick, index) => { - return { - x: tick.x, - y: tick.y, - name: 'Sockets', - label: `${tick.x} Sockets: ${tick.y}` - }; - }); - return } />; - } - - this.renderCoresBars = () => { - let coresBars = this.bars.map((tick, index) => { - return { - x: tick.x, - y: tick.y, - name: 'Cores', - label: `${tick.x} Cores: ${tick.y}` - }; - }); - return } />; - } - - this.renderNodesBars = () => { - let nodesBars = this.bars.map((tick, index) => { - return { - key: index, - x: tick.x, - y: tick.y, - name: 'Nodes', - label: `${tick.x} Nodes: ${tick.y}` - }; - }); - return } />; - } - - this.getTickValues = (offset = 2) => { - let tickValues = []; - for(let i = 1; i < 32; i++){ - if (i % offset == 0){ - tickValues.push(`Aug. ${i}`); - } - } - return tickValues; - } - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render(){ - const { width } = this.state; - return ( -
    -
    - - - - - { this.renderSocketBars() } - { this.renderCoresBars() } - { this.renderNodesBars() } - - -
    -
    - ) - } -} -``` - -### Multi-color (unordered) responsive container - -This demonstrates monthly data with a bottom aligned legend and responsiveness for mobile. - -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartStack, ChartLegendTooltip, ChartThemeColor, ChartVoronoiContainer, createContainer, getResizeObserver } from '@patternfly/react-charts'; - -class MultiColorChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if(this.containerRef.current && this.containerRef.current.clientWidth){ - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - - // Note: Container order is important - const CursorVoronoiContainer = createContainer("voronoi", "cursor"); - const legendData = [{ childName: 'cats', name: 'Cats' }, { childName: 'dogs', name: 'Dogs' }, { childName: 'birds', name: 'Birds' }]; - - return ( -
    -
    - `${datum.y !== null ? datum.y : 'no data'}`} - labelComponent={ datum.x}/>} - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - } - legendData={legendData} - legendPosition="bottom-left" - height={225} - padding={{ - bottom: 75, // Adjusted to accomodate legend - left: 50, - right: 50, - top: 50, - }} - maxDomain={{y: 30}} - themeColor={ChartThemeColor.multiUnordered} - width={width} - > - - - - - - - - -
    -
    - ); - } -} -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` -- Themes are inherited, so a default theme may override `themeColor` for a child component -- The `theme` and `themeColor` props should be applied at the most top level component - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) - - For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) - - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) - - For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) - - For `ChartStack` props, see [VictoryStack](https://formidable.com/open-source/victory/docs/victory-stack) - - For `ChartTooltip` props, see [VictoryTooltip](https://formidable.com/open-source/victory/docs/victory-tooltip) diff --git a/packages/react-charts/src/components/ChartStack/index.ts b/packages/react-charts/src/components/ChartStack/index.ts deleted file mode 100644 index 4ee6254caec..00000000000 --- a/packages/react-charts/src/components/ChartStack/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartStack'; diff --git a/packages/react-charts/src/components/ChartTheme/ChartStyles.ts b/packages/react-charts/src/components/ChartTheme/ChartStyles.ts deleted file mode 100644 index e88bf0b6828..00000000000 --- a/packages/react-charts/src/components/ChartTheme/ChartStyles.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CommonStyles } from './styles/common-styles'; -import { BulletStyles } from './styles/bullet-styles'; -import { DonutStyles } from './styles/donut-styles'; -import { DonutUtilizationStyles } from './styles/donut-utilization-styles'; -import { LegendTooltipStyles } from './styles/legend-tooltip-styles'; -import { ScatterStyles } from './styles/scatter-styles'; - -export const ChartCommonStyles = CommonStyles; -export const ChartBulletStyles = BulletStyles; -export const ChartDonutStyles = DonutStyles; -export const ChartDonutUtilizationStyles = DonutUtilizationStyles; -export const ChartLegendTooltipStyles = LegendTooltipStyles; -export const ChartScatterStyles = ScatterStyles; diff --git a/packages/react-charts/src/components/ChartTheme/ChartTheme.ts b/packages/react-charts/src/components/ChartTheme/ChartTheme.ts deleted file mode 100644 index 5ce979e42dc..00000000000 --- a/packages/react-charts/src/components/ChartTheme/ChartTheme.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { VictoryThemeDefinition } from 'victory-core'; -import { AxisTheme } from './themes/axis-theme'; -import { BaseTheme } from './themes/base-theme'; -import { - BulletTheme, - BulletComparativeErrorMeasureTheme, - BulletComparativeMeasureTheme, - BulletComparativeWarningMeasureTheme, - BulletGroupTitleTheme, - BulletPrimaryDotMeasureTheme, - BulletPrimaryNegativeMeasureTheme, - BulletPrimarySegmentedMeasureTheme, - BulletQualitativeRangeTheme -} from './themes/bullet-theme'; -import { DonutTheme } from './themes/donut-theme'; -import { ThresholdTheme } from './themes/threshold-theme'; -import { DonutThresholdDynamicTheme, DonutThresholdStaticTheme } from './themes/donut-threshold-theme'; -import { DonutUtilizationDynamicTheme, DonutUtilizationStaticTheme } from './themes/donut-utilization-theme'; - -// Note: Victory incorrectly typed ThemeBaseProps.padding as number instead of PaddingProps -export interface ChartThemeDefinitionInterface extends VictoryThemeDefinition {} - -interface ChartThemeColorInterface { - blue: string; - cyan: string; - default: string; - gold: string; - gray: string; - green: string; - multi: string; - multiOrdered: string; - multiUnordered: string; - orange: string; - purple: string; -} - -interface ChartThemeVariantInterface { - dark: string; - default: string; - light: string; -} - -/** - * The color family to be applied to a theme. For example, 'blue' represents an ordered list of colors - * (i.e., a color scale) composed from the blue color family defined by PatternFly core. - * - * For example, the 'blue' color scale looks like: - * - * chart_color_blue_100 - * chart_color_blue_200 - * chart_color_blue_300 - * chart_color_blue_400 - * chart_color_blue_500 - * - * In this case, the chart_color_blue_100 value would be applied to the first data point in a chart. - * The chart_color_blue_200 value would be applied to the second data point in a chart. And so on... - * - * If legend data is provided to a chart, those colors would be synced with the legend as well. - * - * The 'multiOrdered' color family is intended for ordered charts; donut, pie, bar, & stack - * The 'multiUnordered' color family is intended for unordered charts; area & line - * The 'multi' defaults to the 'multiOrdered' color family - * - * Note: These values are not intended to be applied directly as a component's fill style. For example, "multi" would - * not be a valid fill color. Please use chart variables from PatternFly core (e.g., via the react-charts package) - */ -export const ChartThemeColor: ChartThemeColorInterface = { - blue: 'blue', - cyan: 'cyan', - default: 'blue', - gold: 'gold', - gray: 'gray', - green: 'green', - multi: 'multi', - multiOrdered: 'multi-ordered', - multiUnordered: 'multi-unordered', - orange: 'orange', - purple: 'purple' -}; - -/** - * The variant to be applied to a theme. - * - * Note: Only the light variant is currently supported - */ -export const ChartThemeVariant: ChartThemeVariantInterface = { - dark: 'dark', - default: 'light', - light: 'light' -}; - -export type ChartThemeDefinition = ChartThemeDefinitionInterface; - -export const ChartAxisTheme: ChartThemeDefinition = AxisTheme; -export const ChartBaseTheme: ChartThemeDefinition = BaseTheme; -export const ChartBulletComparativeErrorMeasureTheme: ChartThemeDefinition = BulletComparativeErrorMeasureTheme; -export const ChartBulletComparativeMeasureTheme: ChartThemeDefinition = BulletComparativeMeasureTheme; -export const ChartBulletComparativeWarningMeasureTheme: ChartThemeDefinition = BulletComparativeWarningMeasureTheme; -export const ChartBulletGroupTitleTheme: ChartThemeDefinition = BulletGroupTitleTheme; -export const ChartBulletPrimaryDotMeasureTheme: ChartThemeDefinition = BulletPrimaryDotMeasureTheme; -export const ChartBulletPrimaryNegativeMeasureTheme: ChartThemeDefinition = BulletPrimaryNegativeMeasureTheme; -export const ChartBulletPrimarySegmentedMeasureTheme: ChartThemeDefinition = BulletPrimarySegmentedMeasureTheme; -export const ChartBulletTheme: ChartThemeDefinition = BulletTheme; -export const ChartBulletQualitativeRangeTheme: ChartThemeDefinition = BulletQualitativeRangeTheme; -export const ChartDonutUtilizationDynamicTheme: ChartThemeDefinition = DonutUtilizationDynamicTheme; -export const ChartDonutUtilizationStaticTheme: ChartThemeDefinition = DonutUtilizationStaticTheme; -export const ChartDonutTheme: ChartThemeDefinition = DonutTheme; -export const ChartDonutThresholdDynamicTheme: ChartThemeDefinition = DonutThresholdDynamicTheme; -export const ChartDonutThresholdStaticTheme: ChartThemeDefinition = DonutThresholdStaticTheme; -export const ChartThresholdTheme: ChartThemeDefinition = ThresholdTheme; diff --git a/packages/react-charts/src/components/ChartTheme/examples/ChartTheme.md b/packages/react-charts/src/components/ChartTheme/examples/ChartTheme.md deleted file mode 100644 index dc6317ebfa6..00000000000 --- a/packages/react-charts/src/components/ChartTheme/examples/ChartTheme.md +++ /dev/null @@ -1,489 +0,0 @@ ---- -id: Themed charts -section: charts -hideDarkMode: true ---- - -import { - Chart, - ChartArea, - ChartAxis, - ChartBar, - ChartDonut, - ChartGroup, - ChartLegend, - ChartLine, - ChartStack, - ChartThemeColor, - ChartThemeVariant, - ChartThreshold, - ChartTooltip, - ChartVoronoiContainer, - getCustomTheme -} from '@patternfly/react-charts'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -## Examples -### Green - -This demonstrates how to apply basic theme colors. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendData={[{ name: 'Cats' }, { name: 'Dogs', symbol: { type: 'dash' } }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.green} - width={450} - > - - - - - - - - - -
    -``` - -### Multi-color (ordered) - -This demonstrates how to apply theme colors for ordered charts like bar, donut, pie, and stack. - -```js -import React from 'react'; -import { ChartDonut, ChartThemeColor, ChartThemeVariant } from '@patternfly/react-charts'; - -
    - `${datum.x}: ${datum.y}%`} - legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} - legendOrientation="vertical" - legendPosition="right" - padding={{ - bottom: 20, - left: 20, - right: 140, // Adjusted to accommodate legend - top: 20 - }} - subTitle="Pets" - title="100" - themeColor={ChartThemeColor.multiOrdered} - width={350} - /> -
    -``` - -### Multi color (unordered) - -This demonstrates how to apply theme colors for unordered charts like area, line, and sparkline. - -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // Required for mix-blend-mode CSS property - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]} - legendOrientation="vertical" - legendPosition="right" - height={200} - maxDomain={{y: 9}} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - themeColor={ChartThemeColor.multiUnordered} - width={800} - > - - - - - - - - -
    -``` - -### Custom color scale - -This demonstrates an alternate way of applying a custom color scale and fill colors to individual charts. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartLegend, ChartStack, ChartThemeColor, ChartTooltip } from '@patternfly/react-charts'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; - -
    - - } - legendPosition="bottom-left" - height={275} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.multiOrdered} - width={450} - > - - - - } - /> - } - /> - } - /> - } - /> - - -
    -``` - -### Custom stroke color - -This demonstrates an alternate way of applying custom stroke and fill colors to a threshold chart. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, ChartThreshold, ChartVoronoiContainer } from '@patternfly/react-charts'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendData={[ - { name: 'Cats' }, - { name: 'Birds' }, - { name: 'Mice' }, - { name: 'Cats Threshold', symbol: { fill: chart_color_blue_300.value, type: 'threshold' }} - ]} - legendPosition="bottom" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.multiUnordered} - width={450} - > - - - - - - - - - -
    -``` - -### Custom theme - -This demonstrates custom theme properties, which may be applied across multiple charts. - -```js -import React from 'react'; -import { Chart, ChartBar, ChartAxis, ChartGroup, ChartThemeColor, ChartThemeVariant, ChartVoronoiContainer, getCustomTheme } from '@patternfly/react-charts'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; - -class MultiColorChart extends React.Component { - constructor(props) { - super(props); - - // Colors - this.colorScale = [ - chart_color_blue_300.value, - chart_color_green_300.value, - chart_color_cyan_300.value, - chart_color_gold_300.value - ]; - - // Layout - this.layoutProps = { - padding: { - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - } - }; - - // Victory theme properties only - this.themeProps = { - bar: { - colorScale: this.colorScale, - ...this.layoutProps, - }, - chart: { - colorScale: this.colorScale, - ...this.layoutProps, - }, - group: { - colorScale: this.colorScale, - ...this.layoutProps, - }, - legend: { - colorScale: this.colorScale - } - }; - - // Applies theme color and variant to base theme - this.myCustomTheme = getCustomTheme( - ChartThemeColor.default, - ChartThemeVariant.default, - this.themeProps - ); - } - - render() { - return ( -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - domain={{y: [0,9]}} - domainPadding={{ x: [30, 25] }} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} - legendOrientation="vertical" - legendPosition="right" - height={250} - theme={this.myCustomTheme} - width={600} - > - - - - - - - - - -
    - ); - } -} -``` - -## Documentation - -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- The `theme` and `themeColor` props should be applied at the most top level component -- Use `ChartGroup` to apply theme color scales and other properties to multiple components - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For theme props, see [VictoryTheme](https://formidable.com/open-source/victory/docs/victory-theme) diff --git a/packages/react-charts/src/components/ChartTheme/index.ts b/packages/react-charts/src/components/ChartTheme/index.ts deleted file mode 100644 index 15add75cb0b..00000000000 --- a/packages/react-charts/src/components/ChartTheme/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './ChartTheme'; -export * from './ChartStyles'; diff --git a/packages/react-charts/src/components/ChartTheme/styles/common-styles.ts b/packages/react-charts/src/components/ChartTheme/styles/common-styles.ts deleted file mode 100644 index b483a6fb624..00000000000 --- a/packages/react-charts/src/components/ChartTheme/styles/common-styles.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-disable camelcase */ -import chart_global_FontFamily from '@patternfly/react-tokens/dist/esm/chart_global_FontFamily'; -import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; -import chart_global_label_Margin from '@patternfly/react-tokens/dist/esm/chart_global_label_Margin'; -import chart_global_letter_spacing from '@patternfly/react-tokens/dist/esm/chart_global_letter_spacing'; -import chart_legend_Margin from '@patternfly/react-tokens/dist/esm/chart_legend_Margin'; -import chart_legend_position from '@patternfly/react-tokens/dist/esm/chart_legend_position'; - -// Typography -const TYPOGRAPHY_FONT_FAMILY = chart_global_FontFamily.var; -const TYPOGRAPHY_LETTER_SPACING = chart_global_letter_spacing.var; -const TYPOGRAPHY_FONT_SIZE = chart_global_FontSize_sm.value; - -export const CommonStyles = { - label: { - fontFamily: TYPOGRAPHY_FONT_FAMILY, - fontSize: TYPOGRAPHY_FONT_SIZE, - letterSpacing: TYPOGRAPHY_LETTER_SPACING, - margin: chart_global_label_Margin.value - }, - legend: { - margin: chart_legend_Margin.value, - position: chart_legend_position.value - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/styles/donut-styles.ts b/packages/react-charts/src/components/ChartTheme/styles/donut-styles.ts deleted file mode 100644 index bb6bfa8fa8a..00000000000 --- a/packages/react-charts/src/components/ChartTheme/styles/donut-styles.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; -import chart_global_FontSize_2xl from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_2xl'; -import chart_donut_label_subtitle_Fill from '@patternfly/react-tokens/dist/esm/chart_donut_label_subtitle_Fill'; -import chart_donut_label_subtitle_position from '@patternfly/react-tokens/dist/esm/chart_donut_label_subtitle_position'; - -// Donut styles -export const DonutStyles = { - label: { - subTitle: { - // Victory props only - fill: chart_donut_label_subtitle_Fill.value, - fontSize: chart_global_FontSize_sm.value - }, - subTitlePosition: chart_donut_label_subtitle_position.value, - title: { - // Victory props only - fontSize: chart_global_FontSize_2xl.value - } - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/styles/donut-utilization-styles.ts b/packages/react-charts/src/components/ChartTheme/styles/donut-utilization-styles.ts deleted file mode 100644 index 0654ac6eda9..00000000000 --- a/packages/react-charts/src/components/ChartTheme/styles/donut-utilization-styles.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-disable camelcase */ -import chart_donut_threshold_warning_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_warning_Color'; -import chart_donut_threshold_danger_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_danger_Color'; - -// Donut utilization styles -export const DonutUtilizationStyles = { - thresholds: { - colorScale: [chart_donut_threshold_warning_Color.value, chart_donut_threshold_danger_Color.value] - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/styles/legend-tooltip-styles.ts b/packages/react-charts/src/components/ChartTheme/styles/legend-tooltip-styles.ts deleted file mode 100644 index 8064b246fc5..00000000000 --- a/packages/react-charts/src/components/ChartTheme/styles/legend-tooltip-styles.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable camelcase */ -import global_FontWeight_bold from '@patternfly/react-tokens/dist/esm/global_FontWeight_bold'; -import chart_voronoi_labels_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Fill'; - -// Legend tooltip styles -export const LegendTooltipStyles = { - flyout: { - padding: 40 - }, - label: { - fill: chart_voronoi_labels_Fill.value, - fontWeight: global_FontWeight_bold.value - } as any -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/axis-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/axis-theme.ts deleted file mode 100644 index 9d1952757cb..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/axis-theme.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* eslint-disable camelcase */ -import chart_axis_grid_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_grid_stroke_Color'; -import chart_axis_tick_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_tick_stroke_Color'; - -// Axis theme -export const AxisTheme = { - axis: { - style: { - grid: { - stroke: chart_axis_grid_stroke_Color.value - }, - ticks: { - stroke: chart_axis_tick_stroke_Color.value - } - } - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/base-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/base-theme.ts deleted file mode 100644 index 084070f8a66..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/base-theme.ts +++ /dev/null @@ -1,368 +0,0 @@ -/* eslint-disable camelcase */ -import chart_global_FontFamily from '@patternfly/react-tokens/dist/esm/chart_global_FontFamily'; -import chart_global_letter_spacing from '@patternfly/react-tokens/dist/esm/chart_global_letter_spacing'; -import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; -import chart_global_label_Padding from '@patternfly/react-tokens/dist/esm/chart_global_label_Padding'; -import chart_global_label_stroke from '@patternfly/react-tokens/dist/esm/chart_global_label_stroke'; -import chart_global_label_text_anchor from '@patternfly/react-tokens/dist/esm/chart_global_label_text_anchor'; -import chart_global_layout_Padding from '@patternfly/react-tokens/dist/esm/chart_global_layout_Padding'; -import chart_global_layout_Height from '@patternfly/react-tokens/dist/esm/chart_global_layout_Height'; -import chart_global_layout_Width from '@patternfly/react-tokens/dist/esm/chart_global_layout_Width'; -import chart_global_stroke_line_cap from '@patternfly/react-tokens/dist/esm/chart_global_stroke_line_cap'; -import chart_global_stroke_line_join from '@patternfly/react-tokens/dist/esm/chart_global_stroke_line_join'; -import chart_area_data_Fill from '@patternfly/react-tokens/dist/esm/chart_area_data_Fill'; -import chart_area_Opacity from '@patternfly/react-tokens/dist/esm/chart_area_Opacity'; -import chart_area_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_area_stroke_Width'; -import chart_axis_axis_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_axis_axis_stroke_Width'; -import chart_axis_axis_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_axis_stroke_Color'; -import chart_axis_axis_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_axis_Fill'; -import chart_axis_axis_label_Padding from '@patternfly/react-tokens/dist/esm/chart_axis_axis_label_Padding'; -import chart_axis_axis_label_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_axis_label_stroke_Color'; -import chart_axis_grid_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_grid_Fill'; -import chart_axis_grid_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_axis_grid_PointerEvents'; -import chart_axis_tick_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_tick_Fill'; -import chart_axis_tick_Size from '@patternfly/react-tokens/dist/esm/chart_axis_tick_Size'; -import chart_axis_tick_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_tick_stroke_Color'; -import chart_axis_tick_Width from '@patternfly/react-tokens/dist/esm/chart_axis_tick_Width'; -import chart_axis_tick_label_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_tick_label_Fill'; -import chart_bar_Width from '@patternfly/react-tokens/dist/esm/chart_bar_Width'; -import chart_bar_data_stroke from '@patternfly/react-tokens/dist/esm/chart_bar_data_stroke'; -import chart_bar_data_Fill from '@patternfly/react-tokens/dist/esm/chart_bar_data_Fill'; -import chart_bar_data_Padding from '@patternfly/react-tokens/dist/esm/chart_bar_data_Padding'; -import chart_bar_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bar_data_stroke_Width'; -import chart_boxplot_max_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_max_Padding'; -import chart_boxplot_max_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_boxplot_max_stroke_Color'; -import chart_boxplot_max_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_max_stroke_Width'; -import chart_boxplot_median_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_median_Padding'; -import chart_boxplot_median_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_boxplot_median_stroke_Color'; -import chart_boxplot_median_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_median_stroke_Width'; -import chart_boxplot_min_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_min_Padding'; -import chart_boxplot_min_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_min_stroke_Width'; -import chart_boxplot_min_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_boxplot_min_stroke_Color'; -import chart_boxplot_lower_quartile_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_lower_quartile_Padding'; -import chart_boxplot_lower_quartile_Fill from '@patternfly/react-tokens/dist/esm/chart_boxplot_lower_quartile_Fill'; -import chart_boxplot_upper_quartile_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_upper_quartile_Padding'; -import chart_boxplot_upper_quartile_Fill from '@patternfly/react-tokens/dist/esm/chart_boxplot_upper_quartile_Fill'; -import chart_boxplot_box_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_box_Width'; -import chart_candelstick_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_candelstick_data_stroke_Width'; -import chart_candelstick_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_candelstick_data_stroke_Color'; -import chart_candelstick_candle_positive_Color from '@patternfly/react-tokens/dist/esm/chart_candelstick_candle_positive_Color'; -import chart_candelstick_candle_negative_Color from '@patternfly/react-tokens/dist/esm/chart_candelstick_candle_negative_Color'; -import chart_errorbar_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_errorbar_BorderWidth'; -import chart_errorbar_data_Fill from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_Fill'; -import chart_errorbar_data_Opacity from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_Opacity'; -import chart_errorbar_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_stroke_Width'; -import chart_errorbar_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_stroke_Color'; -import chart_legend_gutter_Width from '@patternfly/react-tokens/dist/esm/chart_legend_gutter_Width'; -import chart_legend_orientation from '@patternfly/react-tokens/dist/esm/chart_legend_orientation'; -import chart_legend_title_orientation from '@patternfly/react-tokens/dist/esm/chart_legend_title_orientation'; -import chart_legend_data_type from '@patternfly/react-tokens/dist/esm/chart_legend_data_type'; -import chart_legend_title_Padding from '@patternfly/react-tokens/dist/esm/chart_legend_title_Padding'; -import chart_line_data_Fill from '@patternfly/react-tokens/dist/esm/chart_line_data_Fill'; -import chart_line_data_Opacity from '@patternfly/react-tokens/dist/esm/chart_line_data_Opacity'; -import chart_line_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_line_data_stroke_Width'; -import chart_line_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_line_data_stroke_Color'; -import chart_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_pie_Padding'; -import chart_pie_data_Padding from '@patternfly/react-tokens/dist/esm/chart_pie_data_Padding'; -import chart_pie_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_pie_data_stroke_Width'; -import chart_pie_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_pie_data_stroke_Color'; -import chart_pie_labels_Padding from '@patternfly/react-tokens/dist/esm/chart_pie_labels_Padding'; -import chart_pie_Height from '@patternfly/react-tokens/dist/esm/chart_pie_Height'; -import chart_pie_Width from '@patternfly/react-tokens/dist/esm/chart_pie_Width'; -import chart_scatter_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_scatter_data_stroke_Color'; -import chart_scatter_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_scatter_data_stroke_Width'; -import chart_scatter_data_Opacity from '@patternfly/react-tokens/dist/esm/chart_scatter_data_Opacity'; -import chart_scatter_data_Fill from '@patternfly/react-tokens/dist/esm/chart_scatter_data_Fill'; -import chart_stack_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_stack_data_stroke_Width'; -import chart_tooltip_corner_radius from '@patternfly/react-tokens/dist/esm/chart_tooltip_corner_radius'; -import chart_tooltip_pointer_length from '@patternfly/react-tokens/dist/esm/chart_tooltip_pointer_length'; -import chart_tooltip_Fill from '@patternfly/react-tokens/dist/esm/chart_tooltip_Fill'; -import chart_tooltip_flyoutStyle_corner_radius from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_corner_radius'; -import chart_tooltip_flyoutStyle_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_stroke_Width'; -import chart_tooltip_flyoutStyle_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_PointerEvents'; -import chart_tooltip_flyoutStyle_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_stroke_Color'; -import chart_tooltip_flyoutStyle_Fill from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_Fill'; -import chart_tooltip_pointer_Width from '@patternfly/react-tokens/dist/esm/chart_tooltip_pointer_Width'; -import chart_tooltip_Padding from '@patternfly/react-tokens/dist/esm/chart_tooltip_Padding'; -import chart_tooltip_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_tooltip_PointerEvents'; -import chart_voronoi_data_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_data_Fill'; -import chart_voronoi_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_voronoi_data_stroke_Color'; -import chart_voronoi_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_voronoi_data_stroke_Width'; -import chart_voronoi_labels_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Fill'; -import chart_voronoi_labels_Padding from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Padding'; -import chart_voronoi_labels_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_PointerEvents'; -import chart_voronoi_flyout_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_stroke_Width'; -import chart_voronoi_flyout_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_PointerEvents'; -import chart_voronoi_flyout_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_stroke_Color'; -import chart_voronoi_flyout_stroke_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_stroke_Fill'; - -// Note: Values must be in pixles - -// Typography -// -// Note: Victory's approximateTextSize function uses specific character widths and does not work with font variables -// See https://github.com/patternfly/patternfly-react/issues/5300 -const TYPOGRAPHY_FONT_FAMILY = chart_global_FontFamily.value.replace(/ /g, ''); -const TYPOGRAPHY_LETTER_SPACING = chart_global_letter_spacing.value; -const TYPOGRAPHY_FONT_SIZE = chart_global_FontSize_sm.value; - -// Labels -const LABEL_PROPS = { - fontFamily: TYPOGRAPHY_FONT_FAMILY, - fontSize: TYPOGRAPHY_FONT_SIZE, - letterSpacing: TYPOGRAPHY_LETTER_SPACING, - padding: chart_global_label_Padding.value, - stroke: chart_global_label_stroke.value -}; -const LABEL_CENTERED_PROPS = { - ...LABEL_PROPS, - textAnchor: chart_global_label_text_anchor.value -}; - -// Layout -const LAYOUT_PROPS = { - padding: chart_global_layout_Padding.value, - height: chart_global_layout_Height.value, - width: chart_global_layout_Width.value -}; - -// Strokes -const STROKE_LINE_CAP = chart_global_stroke_line_cap.value; -const STROKE_LINE_JOIN = chart_global_stroke_line_join.value; - -// Victory theme properties only -export const BaseTheme = { - area: { - ...LAYOUT_PROPS, - style: { - data: { - fill: chart_area_data_Fill.value, - fillOpacity: chart_area_Opacity.value, - // Omit stroke to add a line border from color scale - // stroke: chart_global_label_stroke.value, - strokeWidth: chart_area_stroke_Width.value - }, - labels: LABEL_CENTERED_PROPS - } - }, - axis: { - ...LAYOUT_PROPS, - style: { - axis: { - fill: chart_axis_axis_Fill.value, - strokeWidth: chart_axis_axis_stroke_Width.value, - stroke: chart_axis_axis_stroke_Color.value, - strokeLinecap: STROKE_LINE_CAP, - strokeLinejoin: STROKE_LINE_JOIN - }, - axisLabel: { - ...LABEL_CENTERED_PROPS, - padding: chart_axis_axis_label_Padding.value, - stroke: chart_axis_axis_label_stroke_Color.value - }, - grid: { - fill: chart_axis_grid_Fill.value, - stroke: 'none', - pointerEvents: chart_axis_grid_PointerEvents.value, - strokeLinecap: STROKE_LINE_CAP, - strokeLinejoin: STROKE_LINE_JOIN - }, - ticks: { - fill: chart_axis_tick_Fill.value, - size: chart_axis_tick_Size.value, - stroke: chart_axis_tick_stroke_Color.value, - strokeLinecap: STROKE_LINE_CAP, - strokeLinejoin: STROKE_LINE_JOIN, - strokeWidth: chart_axis_tick_Width.value - }, - tickLabels: { - ...LABEL_PROPS, - fill: chart_axis_tick_label_Fill.value - } - } - }, - bar: { - ...LAYOUT_PROPS, - barWidth: chart_bar_Width.value, - style: { - data: { - fill: chart_bar_data_Fill.value, - padding: chart_bar_data_Padding.value, - stroke: chart_bar_data_stroke.value, - strokeWidth: chart_bar_data_stroke_Width.value - }, - labels: LABEL_PROPS - } - }, - boxplot: { - ...LAYOUT_PROPS, - style: { - max: { - padding: chart_boxplot_max_Padding.value, - stroke: chart_boxplot_max_stroke_Color.value, - strokeWidth: chart_boxplot_max_stroke_Width.value - }, - maxLabels: LABEL_PROPS, - median: { - padding: chart_boxplot_median_Padding.value, - stroke: chart_boxplot_median_stroke_Color.value, - strokeWidth: chart_boxplot_median_stroke_Width.value - }, - medianLabels: LABEL_PROPS, - min: { - padding: chart_boxplot_min_Padding.value, - stroke: chart_boxplot_min_stroke_Color.value, - strokeWidth: chart_boxplot_min_stroke_Width.value - }, - minLabels: LABEL_PROPS, - q1: { - fill: chart_boxplot_lower_quartile_Fill.value, - padding: chart_boxplot_lower_quartile_Padding.value - }, - q1Labels: LABEL_PROPS, - q3: { - fill: chart_boxplot_upper_quartile_Fill.value, - padding: chart_boxplot_upper_quartile_Padding.value - }, - q3Labels: LABEL_PROPS - }, - boxWidth: chart_boxplot_box_Width.value - }, - candlestick: { - ...LAYOUT_PROPS, - candleColors: { - positive: chart_candelstick_candle_positive_Color.value, - negative: chart_candelstick_candle_negative_Color.value - }, - style: { - data: { - stroke: chart_candelstick_data_stroke_Color.value, - strokeWidth: chart_candelstick_data_stroke_Width.value - }, - labels: LABEL_CENTERED_PROPS - } - }, - chart: { - ...LAYOUT_PROPS - }, - errorbar: { - ...LAYOUT_PROPS, - borderWidth: chart_errorbar_BorderWidth.value, - style: { - data: { - fill: chart_errorbar_data_Fill.value, - opacity: chart_errorbar_data_Opacity.value, - stroke: chart_errorbar_data_stroke_Color.value, - strokeWidth: chart_errorbar_data_stroke_Width.value - }, - labels: LABEL_CENTERED_PROPS - } - }, - group: { - ...LAYOUT_PROPS - }, - legend: { - gutter: chart_legend_gutter_Width.value, - orientation: chart_legend_orientation.value, - titleOrientation: chart_legend_title_orientation.value, - style: { - data: { - type: chart_legend_data_type.value - }, - labels: LABEL_PROPS, - title: { - ...LABEL_PROPS, - fontSize: TYPOGRAPHY_FONT_SIZE, - padding: chart_legend_title_Padding.value - } - } - }, - line: { - ...LAYOUT_PROPS, - style: { - data: { - fill: chart_line_data_Fill.value, - opacity: chart_line_data_Opacity.value, - stroke: chart_line_data_stroke_Color.value, - strokeWidth: chart_line_data_stroke_Width.value - }, - labels: LABEL_CENTERED_PROPS - } - }, - pie: { - padding: chart_pie_Padding.value, - style: { - data: { - padding: chart_pie_data_Padding.value, - stroke: chart_pie_data_stroke_Color.value, - strokeWidth: chart_pie_data_stroke_Width.value - }, - labels: { - ...LABEL_PROPS, - padding: chart_pie_labels_Padding.value - } - }, - height: chart_pie_Height.value, - width: chart_pie_Width.value - }, - scatter: { - ...LAYOUT_PROPS, - style: { - data: { - fill: chart_scatter_data_Fill.value, - opacity: chart_scatter_data_Opacity.value, - stroke: chart_scatter_data_stroke_Color.value, - strokeWidth: chart_scatter_data_stroke_Width.value - }, - labels: LABEL_CENTERED_PROPS - } - }, - stack: { - ...LAYOUT_PROPS, - style: { - data: { - strokeWidth: chart_stack_data_stroke_Width.value - } - } - }, - tooltip: { - cornerRadius: chart_tooltip_corner_radius.value, - flyoutPadding: chart_tooltip_Padding.value, - flyoutStyle: { - cornerRadius: chart_tooltip_flyoutStyle_corner_radius.value, - fill: chart_tooltip_flyoutStyle_Fill.value, // background - pointerEvents: chart_tooltip_flyoutStyle_PointerEvents.value, - stroke: chart_tooltip_flyoutStyle_stroke_Color.value, // border - strokeWidth: chart_tooltip_flyoutStyle_stroke_Width.value - }, - pointerLength: chart_tooltip_pointer_length.value, - pointerWidth: chart_tooltip_pointer_Width.value, - style: { - fill: chart_tooltip_Fill.value, // text - pointerEvents: chart_tooltip_PointerEvents.value - } - }, - voronoi: { - ...LAYOUT_PROPS, - style: { - data: { - fill: chart_voronoi_data_Fill.value, - stroke: chart_voronoi_data_stroke_Color.value, - strokeWidth: chart_voronoi_data_stroke_Width.value - }, - labels: { - ...LABEL_CENTERED_PROPS, - fill: chart_voronoi_labels_Fill.value, // text - padding: chart_voronoi_labels_Padding.value, - pointerEvents: chart_voronoi_labels_PointerEvents.value - }, - // Note: These properties override tooltip - flyout: { - fill: chart_voronoi_flyout_stroke_Fill.value, // background - pointerEvents: chart_voronoi_flyout_PointerEvents.value, - stroke: chart_voronoi_flyout_stroke_Color.value, // border - strokeWidth: chart_voronoi_flyout_stroke_Width.value - } - } - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/bullet-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/bullet-theme.ts deleted file mode 100644 index 6d7a9cd40ad..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/bullet-theme.ts +++ /dev/null @@ -1,140 +0,0 @@ -/* eslint-disable camelcase */ -import chart_bullet_Height from '@patternfly/react-tokens/dist/esm/chart_bullet_Height'; -import chart_bullet_comparative_measure_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_Fill_Color'; -import chart_bullet_comparative_measure_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_stroke_Color'; -import chart_bullet_comparative_measure_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_stroke_Width'; -import chart_bullet_comparative_measure_error_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_error_Fill_Color'; -import chart_bullet_comparative_measure_error_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_error_stroke_Color'; -import chart_bullet_comparative_measure_error_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_error_stroke_Width'; -import chart_bullet_comparative_measure_warning_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_warning_Fill_Color'; -import chart_bullet_comparative_measure_warning_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_warning_stroke_Color'; -import chart_bullet_comparative_measure_warning_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_warning_stroke_Width'; -import chart_bullet_group_title_divider_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_group_title_divider_Fill_Color'; -import chart_bullet_group_title_divider_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_group_title_divider_stroke_Color'; -import chart_bullet_group_title_divider_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_group_title_divider_stroke_Width'; -import chart_color_black_100 from '@patternfly/react-tokens/dist/esm/chart_color_black_100'; -import chart_color_black_200 from '@patternfly/react-tokens/dist/esm/chart_color_black_200'; -import chart_color_black_300 from '@patternfly/react-tokens/dist/esm/chart_color_black_300'; -import chart_color_black_400 from '@patternfly/react-tokens/dist/esm/chart_color_black_400'; -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; -import chart_color_red_100 from '@patternfly/react-tokens/dist/esm/chart_color_red_100'; -import chart_color_red_200 from '@patternfly/react-tokens/dist/esm/chart_color_red_200'; -import chart_color_red_300 from '@patternfly/react-tokens/dist/esm/chart_color_red_300'; -import chart_color_red_400 from '@patternfly/react-tokens/dist/esm/chart_color_red_400'; -import chart_color_red_500 from '@patternfly/react-tokens/dist/esm/chart_color_red_500'; -import chart_global_layout_Padding from '@patternfly/react-tokens/dist/esm/chart_global_layout_Padding'; - -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit# -// See https://www.patternfly.org/v3/pattern-library/data-visualization/bullet-chart/#design - -// Bullet theme -export const BulletTheme = { - chart: { - height: chart_bullet_Height.value - } -}; - -// Bullet comparative measure error theme -export const BulletComparativeErrorMeasureTheme = { - bar: { - height: chart_bullet_Height.value, - style: { - data: { - fill: chart_bullet_comparative_measure_error_Fill_Color.value, - stroke: chart_bullet_comparative_measure_error_stroke_Color.value, - strokeWidth: chart_bullet_comparative_measure_error_stroke_Width.value - } - } - } -}; - -// Bullet comparative measure theme -export const BulletComparativeMeasureTheme = { - bar: { - height: chart_bullet_Height.value, - style: { - data: { - fill: chart_bullet_comparative_measure_Fill_Color.value, - stroke: chart_bullet_comparative_measure_stroke_Color.value, - strokeWidth: chart_bullet_comparative_measure_stroke_Width.value - } - } - } -}; - -// Bullet comparative measure warning theme -export const BulletComparativeWarningMeasureTheme = { - bar: { - height: chart_bullet_Height.value, - style: { - data: { - fill: chart_bullet_comparative_measure_warning_Fill_Color.value, - stroke: chart_bullet_comparative_measure_warning_stroke_Color.value, - strokeWidth: chart_bullet_comparative_measure_warning_stroke_Width.value - } - } - } -}; - -// Bullet group title theme -export const BulletGroupTitleTheme = { - chart: { - padding: { - bottom: 0, - left: 0, - right: 0, - top: chart_global_layout_Padding.value - } as any // Victory incorrectly typed ThemeBaseProps.padding as number instead of PaddingProps - }, - line: { - style: { - data: { - fill: chart_bullet_group_title_divider_Fill_Color.value, - stroke: chart_bullet_group_title_divider_stroke_Color.value, - strokeWidth: chart_bullet_group_title_divider_stroke_Width.value - } - } - } -}; - -// Bullet primary dot measure theme -export const BulletPrimaryDotMeasureTheme = { - group: { - height: chart_bullet_Height.value - } -}; - -// Bullet primary negative measure theme -export const BulletPrimaryNegativeMeasureTheme = { - group: { - colorScale: [ - chart_color_red_100.value, - chart_color_red_200.value, - chart_color_red_300.value, - chart_color_red_400.value, - chart_color_red_500.value - ], - height: chart_bullet_Height.value - } -}; - -// Bullet primary segmented measure theme -export const BulletPrimarySegmentedMeasureTheme = { - group: { - height: chart_bullet_Height.value - } -}; - -// Bullet qualitative range theme -export const BulletQualitativeRangeTheme = { - group: { - colorScale: [ - chart_color_black_100.value, - chart_color_black_200.value, - chart_color_black_300.value, - chart_color_black_400.value, - chart_color_black_500.value - ], - height: chart_bullet_Height.value - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/color-theme.ts deleted file mode 100644 index 00ff87b38de..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/color-theme.ts +++ /dev/null @@ -1,68 +0,0 @@ -interface ColorThemeInterface { - COLOR_SCALE: string[]; -} - -// Victory theme properties only -export const ColorTheme = (props: ColorThemeInterface) => { - const { COLOR_SCALE } = props; - - return { - area: { - colorScale: COLOR_SCALE, - style: { - data: { - fill: COLOR_SCALE[0] - } - } - }, - axis: { - colorScale: COLOR_SCALE - }, - bar: { - colorScale: COLOR_SCALE, - style: { - data: { - fill: COLOR_SCALE[0] - } - } - }, - boxplot: { - colorScale: COLOR_SCALE - }, - candlestick: { - colorScale: COLOR_SCALE - }, - chart: { - colorScale: COLOR_SCALE - }, - errorbar: { - colorScale: COLOR_SCALE - }, - group: { - colorScale: COLOR_SCALE - }, - legend: { - colorScale: COLOR_SCALE - }, - line: { - colorScale: COLOR_SCALE, - style: { - data: { - stroke: COLOR_SCALE[0] - } - } - }, - pie: { - colorScale: COLOR_SCALE - }, - scatter: { - colorScale: COLOR_SCALE - }, - stack: { - colorScale: COLOR_SCALE - }, - voronoi: { - colorScale: COLOR_SCALE - } - }; -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/blue-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/blue-color-theme.ts deleted file mode 100644 index a363e11fbb5..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/blue-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_blue_100 from '@patternfly/react-tokens/dist/esm/chart_color_blue_100'; -import chart_color_blue_200 from '@patternfly/react-tokens/dist/esm/chart_color_blue_200'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_blue_400 from '@patternfly/react-tokens/dist/esm/chart_color_blue_400'; -import chart_color_blue_500 from '@patternfly/react-tokens/dist/esm/chart_color_blue_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_blue_300.value, - chart_color_blue_100.value, - chart_color_blue_500.value, - chart_color_blue_200.value, - chart_color_blue_400.value -]; - -export const DarkBlueColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/cyan-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/cyan-color-theme.ts deleted file mode 100644 index 1a227ef3138..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/cyan-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_cyan_100 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_100'; -import chart_color_cyan_200 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_200'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_cyan_400 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_400'; -import chart_color_cyan_500 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_cyan_300.value, - chart_color_cyan_100.value, - chart_color_cyan_500.value, - chart_color_cyan_200.value, - chart_color_cyan_400.value -]; - -export const DarkCyanColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/gold-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/gold-color-theme.ts deleted file mode 100644 index 82edb12f22b..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/gold-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_gold_100 from '@patternfly/react-tokens/dist/esm/chart_color_gold_100'; -import chart_color_gold_200 from '@patternfly/react-tokens/dist/esm/chart_color_gold_200'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_gold_400 from '@patternfly/react-tokens/dist/esm/chart_color_gold_400'; -import chart_color_gold_500 from '@patternfly/react-tokens/dist/esm/chart_color_gold_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_gold_300.value, - chart_color_gold_100.value, - chart_color_gold_500.value, - chart_color_gold_200.value, - chart_color_gold_400.value -]; - -export const DarkGoldColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/gray-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/gray-color-theme.ts deleted file mode 100644 index c2ae0954c05..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/gray-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_black_100 from '@patternfly/react-tokens/dist/esm/chart_color_black_100'; -import chart_color_black_200 from '@patternfly/react-tokens/dist/esm/chart_color_black_200'; -import chart_color_black_300 from '@patternfly/react-tokens/dist/esm/chart_color_black_300'; -import chart_color_black_400 from '@patternfly/react-tokens/dist/esm/chart_color_black_400'; -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_black_300.value, - chart_color_black_100.value, - chart_color_black_500.value, - chart_color_black_200.value, - chart_color_black_400.value -]; - -export const DarkGrayColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/green-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/green-color-theme.ts deleted file mode 100644 index 5d5f44ac5e4..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/green-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_green_100 from '@patternfly/react-tokens/dist/esm/chart_color_green_100'; -import chart_color_green_200 from '@patternfly/react-tokens/dist/esm/chart_color_green_200'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_green_400 from '@patternfly/react-tokens/dist/esm/chart_color_green_400'; -import chart_color_green_500 from '@patternfly/react-tokens/dist/esm/chart_color_green_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_green_300.value, - chart_color_green_100.value, - chart_color_green_500.value, - chart_color_green_200.value, - chart_color_green_400.value -]; - -export const DarkGreenColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/multi-color-ordered-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/multi-color-ordered-theme.ts deleted file mode 100644 index 4aa36b76bfd..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/multi-color-ordered-theme.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_blue_100 from '@patternfly/react-tokens/dist/esm/chart_color_blue_100'; -import chart_color_blue_200 from '@patternfly/react-tokens/dist/esm/chart_color_blue_200'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_blue_400 from '@patternfly/react-tokens/dist/esm/chart_color_blue_400'; -import chart_color_blue_500 from '@patternfly/react-tokens/dist/esm/chart_color_blue_500'; -import chart_color_green_100 from '@patternfly/react-tokens/dist/esm/chart_color_green_100'; -import chart_color_green_200 from '@patternfly/react-tokens/dist/esm/chart_color_green_200'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_green_400 from '@patternfly/react-tokens/dist/esm/chart_color_green_400'; -import chart_color_green_500 from '@patternfly/react-tokens/dist/esm/chart_color_green_500'; -import chart_color_cyan_100 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_100'; -import chart_color_cyan_200 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_200'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_cyan_400 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_400'; -import chart_color_cyan_500 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_500'; -import chart_color_gold_100 from '@patternfly/react-tokens/dist/esm/chart_color_gold_100'; -import chart_color_gold_200 from '@patternfly/react-tokens/dist/esm/chart_color_gold_200'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_gold_400 from '@patternfly/react-tokens/dist/esm/chart_color_gold_400'; -import chart_color_gold_500 from '@patternfly/react-tokens/dist/esm/chart_color_gold_500'; -import chart_color_orange_100 from '@patternfly/react-tokens/dist/esm/chart_color_orange_100'; -import chart_color_orange_200 from '@patternfly/react-tokens/dist/esm/chart_color_orange_200'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; -import chart_color_orange_400 from '@patternfly/react-tokens/dist/esm/chart_color_orange_400'; -import chart_color_orange_500 from '@patternfly/react-tokens/dist/esm/chart_color_orange_500'; -import { ColorTheme } from '../color-theme'; - -// The color order below (minus the purple color family) improves the color contrast in ordered charts; donut, pie, bar, & stack -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_blue_300.value, - chart_color_green_300.value, - chart_color_cyan_300.value, - chart_color_gold_300.value, - chart_color_orange_300.value, - chart_color_blue_100.value, - chart_color_green_500.value, - chart_color_cyan_100.value, - chart_color_gold_100.value, - chart_color_orange_500.value, - chart_color_blue_500.value, - chart_color_green_100.value, - chart_color_cyan_500.value, - chart_color_gold_500.value, - chart_color_orange_100.value, - chart_color_blue_200.value, - chart_color_green_400.value, - chart_color_cyan_200.value, - chart_color_gold_200.value, - chart_color_orange_400.value, - chart_color_blue_400.value, - chart_color_green_200.value, - chart_color_cyan_400.value, - chart_color_gold_400.value, - chart_color_orange_200.value -]; - -export const DarkMultiColorOrderedTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/multi-color-unordered-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/multi-color-unordered-theme.ts deleted file mode 100644 index 49b8c193cc1..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/multi-color-unordered-theme.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_blue_100 from '@patternfly/react-tokens/dist/esm/chart_color_blue_100'; -import chart_color_blue_200 from '@patternfly/react-tokens/dist/esm/chart_color_blue_200'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_blue_400 from '@patternfly/react-tokens/dist/esm/chart_color_blue_400'; -import chart_color_blue_500 from '@patternfly/react-tokens/dist/esm/chart_color_blue_500'; -import chart_color_green_100 from '@patternfly/react-tokens/dist/esm/chart_color_green_100'; -import chart_color_green_200 from '@patternfly/react-tokens/dist/esm/chart_color_green_200'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_green_400 from '@patternfly/react-tokens/dist/esm/chart_color_green_400'; -import chart_color_green_500 from '@patternfly/react-tokens/dist/esm/chart_color_green_500'; -import chart_color_cyan_100 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_100'; -import chart_color_cyan_200 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_200'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_cyan_400 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_400'; -import chart_color_cyan_500 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_500'; -import chart_color_purple_100 from '@patternfly/react-tokens/dist/esm/chart_color_purple_100'; -import chart_color_purple_200 from '@patternfly/react-tokens/dist/esm/chart_color_purple_200'; -import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; -import chart_color_purple_400 from '@patternfly/react-tokens/dist/esm/chart_color_purple_400'; -import chart_color_purple_500 from '@patternfly/react-tokens/dist/esm/chart_color_purple_500'; -import chart_color_gold_100 from '@patternfly/react-tokens/dist/esm/chart_color_gold_100'; -import chart_color_gold_200 from '@patternfly/react-tokens/dist/esm/chart_color_gold_200'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_gold_400 from '@patternfly/react-tokens/dist/esm/chart_color_gold_400'; -import chart_color_gold_500 from '@patternfly/react-tokens/dist/esm/chart_color_gold_500'; -import chart_color_orange_100 from '@patternfly/react-tokens/dist/esm/chart_color_orange_100'; -import chart_color_orange_200 from '@patternfly/react-tokens/dist/esm/chart_color_orange_200'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; -import chart_color_orange_400 from '@patternfly/react-tokens/dist/esm/chart_color_orange_400'; -import chart_color_orange_500 from '@patternfly/react-tokens/dist/esm/chart_color_orange_500'; -import chart_color_black_100 from '@patternfly/react-tokens/dist/esm/chart_color_black_100'; -import chart_color_black_200 from '@patternfly/react-tokens/dist/esm/chart_color_black_200'; -import chart_color_black_300 from '@patternfly/react-tokens/dist/esm/chart_color_black_300'; -import chart_color_black_400 from '@patternfly/react-tokens/dist/esm/chart_color_black_400'; -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; -import { ColorTheme } from '../color-theme'; - -// The color order below improves the color contrast in unordered charts; area & line -// See https://github.com/patternfly/patternfly-next/issues/1551 -const COLOR_SCALE = [ - chart_color_blue_300.value, - chart_color_gold_300.value, - chart_color_green_300.value, - chart_color_purple_300.value, - chart_color_orange_300.value, - chart_color_cyan_300.value, - chart_color_black_300.value, - chart_color_blue_100.value, - chart_color_gold_500.value, - chart_color_green_100.value, - chart_color_purple_500.value, - chart_color_orange_100.value, - chart_color_cyan_500.value, - chart_color_black_100.value, - chart_color_blue_500.value, - chart_color_gold_100.value, - chart_color_green_500.value, - chart_color_purple_100.value, - chart_color_orange_500.value, - chart_color_cyan_100.value, - chart_color_black_500.value, - chart_color_blue_200.value, - chart_color_gold_400.value, - chart_color_green_200.value, - chart_color_purple_400.value, - chart_color_orange_200.value, - chart_color_cyan_400.value, - chart_color_black_200.value, - chart_color_blue_400.value, - chart_color_gold_200.value, - chart_color_green_400.value, - chart_color_purple_200.value, - chart_color_orange_400.value, - chart_color_cyan_200.value, - chart_color_black_400.value -]; - -export const DarkMultiColorUnorderedTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/orange-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/orange-color-theme.ts deleted file mode 100644 index c06f3936555..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/orange-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_orange_100 from '@patternfly/react-tokens/dist/esm/chart_color_orange_100'; -import chart_color_orange_200 from '@patternfly/react-tokens/dist/esm/chart_color_orange_200'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; -import chart_color_orange_400 from '@patternfly/react-tokens/dist/esm/chart_color_orange_400'; -import chart_color_orange_500 from '@patternfly/react-tokens/dist/esm/chart_color_orange_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_orange_300.value, - chart_color_orange_100.value, - chart_color_orange_500.value, - chart_color_orange_200.value, - chart_color_orange_400.value -]; - -export const DarkOrangeColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/dark/purple-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/dark/purple-color-theme.ts deleted file mode 100644 index f2cc421607b..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/dark/purple-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_purple_100 from '@patternfly/react-tokens/dist/esm/chart_color_purple_100'; -import chart_color_purple_200 from '@patternfly/react-tokens/dist/esm/chart_color_purple_200'; -import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; -import chart_color_purple_400 from '@patternfly/react-tokens/dist/esm/chart_color_purple_400'; -import chart_color_purple_500 from '@patternfly/react-tokens/dist/esm/chart_color_purple_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_purple_300.value, - chart_color_purple_100.value, - chart_color_purple_500.value, - chart_color_purple_200.value, - chart_color_purple_400.value -]; - -export const DarkPurpleColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/donut-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/donut-theme.ts deleted file mode 100644 index 49fc59b5259..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/donut-theme.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable camelcase */ -import chart_donut_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_pie_Height'; -import chart_donut_pie_angle_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_pie_angle_Padding'; -import chart_donut_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_pie_Padding'; -import chart_donut_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_pie_Width'; - -// Donut theme -export const DonutTheme = { - pie: { - height: chart_donut_pie_Height.value, - padding: chart_donut_pie_Padding.value, - padAngle: chart_donut_pie_angle_Padding.value, - width: chart_donut_pie_Width.value - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/donut-threshold-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/donut-threshold-theme.ts deleted file mode 100644 index 54463256140..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/donut-threshold-theme.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable camelcase */ -import chart_donut_threshold_first_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_first_Color'; -import chart_donut_threshold_second_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_second_Color'; -import chart_donut_threshold_third_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_third_Color'; -import chart_donut_threshold_dynamic_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_dynamic_pie_Height'; -import chart_donut_threshold_dynamic_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_dynamic_pie_Padding'; -import chart_donut_threshold_dynamic_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_dynamic_pie_Width'; -import chart_donut_threshold_static_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_Height'; -import chart_donut_threshold_static_pie_angle_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_angle_Padding'; -import chart_donut_threshold_static_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_Padding'; -import chart_donut_threshold_static_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_Width'; - -// Donut threshold dynamic theme -export const DonutThresholdDynamicTheme = { - legend: { - colorScale: [chart_donut_threshold_second_Color.value, chart_donut_threshold_third_Color.value] - }, - pie: { - height: chart_donut_threshold_dynamic_pie_Height.value, - padding: chart_donut_threshold_dynamic_pie_Padding.value, - width: chart_donut_threshold_dynamic_pie_Width.value - } -}; - -// Donut threshold static theme -export const DonutThresholdStaticTheme = { - pie: { - colorScale: [ - chart_donut_threshold_first_Color.value, - chart_donut_threshold_second_Color.value, - chart_donut_threshold_third_Color.value - ], - height: chart_donut_threshold_static_pie_Height.value, - padAngle: chart_donut_threshold_static_pie_angle_Padding.value, - padding: chart_donut_threshold_static_pie_Padding.value, - width: chart_donut_threshold_static_pie_Width.value - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/donut-utilization-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/donut-utilization-theme.ts deleted file mode 100644 index d9c70b898d9..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/donut-utilization-theme.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-disable camelcase */ -import chart_donut_threshold_first_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_first_Color'; -import chart_donut_threshold_second_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_second_Color'; -import chart_donut_threshold_third_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_third_Color'; -import chart_donut_utilization_dynamic_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_Height'; -import chart_donut_utilization_dynamic_pie_angle_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_angle_Padding'; -import chart_donut_utilization_dynamic_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_Padding'; -import chart_donut_utilization_dynamic_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_Width'; -import chart_donut_utilization_static_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_static_pie_Padding'; - -// Donut utilization dynamic theme -export const DonutUtilizationDynamicTheme = { - pie: { - height: chart_donut_utilization_dynamic_pie_Height.value, - padding: chart_donut_utilization_dynamic_pie_Padding.value, - padAngle: chart_donut_utilization_dynamic_pie_angle_Padding.value, - width: chart_donut_utilization_dynamic_pie_Width.value - } -}; - -// Donut utilization static theme -export const DonutUtilizationStaticTheme = { - legend: { - colorScale: [ - chart_donut_threshold_first_Color.value, - chart_donut_threshold_second_Color.value, - chart_donut_threshold_third_Color.value - ] - }, - pie: { - colorScale: [chart_donut_threshold_first_Color.value], - padding: chart_donut_utilization_static_pie_Padding.value - } -}; diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/blue-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/blue-color-theme.ts deleted file mode 100644 index 8a31e98ead5..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/blue-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_blue_100 from '@patternfly/react-tokens/dist/esm/chart_color_blue_100'; -import chart_color_blue_200 from '@patternfly/react-tokens/dist/esm/chart_color_blue_200'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_blue_400 from '@patternfly/react-tokens/dist/esm/chart_color_blue_400'; -import chart_color_blue_500 from '@patternfly/react-tokens/dist/esm/chart_color_blue_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_blue_300.value, - chart_color_blue_100.value, - chart_color_blue_500.value, - chart_color_blue_200.value, - chart_color_blue_400.value -]; - -export const LightBlueColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/cyan-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/cyan-color-theme.ts deleted file mode 100644 index 5605ed1ea30..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/cyan-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_cyan_100 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_100'; -import chart_color_cyan_200 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_200'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_cyan_400 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_400'; -import chart_color_cyan_500 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_cyan_300.value, - chart_color_cyan_100.value, - chart_color_cyan_500.value, - chart_color_cyan_200.value, - chart_color_cyan_400.value -]; - -export const LightCyanColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/gold-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/gold-color-theme.ts deleted file mode 100644 index e42e8f6d334..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/gold-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_gold_100 from '@patternfly/react-tokens/dist/esm/chart_color_gold_100'; -import chart_color_gold_200 from '@patternfly/react-tokens/dist/esm/chart_color_gold_200'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_gold_400 from '@patternfly/react-tokens/dist/esm/chart_color_gold_400'; -import chart_color_gold_500 from '@patternfly/react-tokens/dist/esm/chart_color_gold_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_gold_300.value, - chart_color_gold_100.value, - chart_color_gold_500.value, - chart_color_gold_200.value, - chart_color_gold_400.value -]; - -export const LightGoldColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/gray-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/gray-color-theme.ts deleted file mode 100644 index 3fb3c16febb..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/gray-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_black_100 from '@patternfly/react-tokens/dist/esm/chart_color_black_100'; -import chart_color_black_200 from '@patternfly/react-tokens/dist/esm/chart_color_black_200'; -import chart_color_black_300 from '@patternfly/react-tokens/dist/esm/chart_color_black_300'; -import chart_color_black_400 from '@patternfly/react-tokens/dist/esm/chart_color_black_400'; -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_black_300.value, - chart_color_black_100.value, - chart_color_black_500.value, - chart_color_black_200.value, - chart_color_black_400.value -]; - -export const LightGrayColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/green-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/green-color-theme.ts deleted file mode 100644 index 3f722a17a29..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/green-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_green_100 from '@patternfly/react-tokens/dist/esm/chart_color_green_100'; -import chart_color_green_200 from '@patternfly/react-tokens/dist/esm/chart_color_green_200'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_green_400 from '@patternfly/react-tokens/dist/esm/chart_color_green_400'; -import chart_color_green_500 from '@patternfly/react-tokens/dist/esm/chart_color_green_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_green_300.value, - chart_color_green_100.value, - chart_color_green_500.value, - chart_color_green_200.value, - chart_color_green_400.value -]; - -export const LightGreenColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/multi-color-ordered-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/multi-color-ordered-theme.ts deleted file mode 100644 index 64194e5bc69..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/multi-color-ordered-theme.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_blue_100 from '@patternfly/react-tokens/dist/esm/chart_color_blue_100'; -import chart_color_blue_200 from '@patternfly/react-tokens/dist/esm/chart_color_blue_200'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_blue_400 from '@patternfly/react-tokens/dist/esm/chart_color_blue_400'; -import chart_color_blue_500 from '@patternfly/react-tokens/dist/esm/chart_color_blue_500'; -import chart_color_green_100 from '@patternfly/react-tokens/dist/esm/chart_color_green_100'; -import chart_color_green_200 from '@patternfly/react-tokens/dist/esm/chart_color_green_200'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_green_400 from '@patternfly/react-tokens/dist/esm/chart_color_green_400'; -import chart_color_green_500 from '@patternfly/react-tokens/dist/esm/chart_color_green_500'; -import chart_color_cyan_100 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_100'; -import chart_color_cyan_200 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_200'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_cyan_400 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_400'; -import chart_color_cyan_500 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_500'; -import chart_color_gold_100 from '@patternfly/react-tokens/dist/esm/chart_color_gold_100'; -import chart_color_gold_200 from '@patternfly/react-tokens/dist/esm/chart_color_gold_200'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_gold_400 from '@patternfly/react-tokens/dist/esm/chart_color_gold_400'; -import chart_color_gold_500 from '@patternfly/react-tokens/dist/esm/chart_color_gold_500'; -import chart_color_orange_100 from '@patternfly/react-tokens/dist/esm/chart_color_orange_100'; -import chart_color_orange_200 from '@patternfly/react-tokens/dist/esm/chart_color_orange_200'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; -import chart_color_orange_400 from '@patternfly/react-tokens/dist/esm/chart_color_orange_400'; -import chart_color_orange_500 from '@patternfly/react-tokens/dist/esm/chart_color_orange_500'; -import { ColorTheme } from '../color-theme'; - -// The color order below (minus the purple color family) improves the color contrast in ordered charts; donut, pie, bar, & stack -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_blue_300.value, - chart_color_green_300.value, - chart_color_cyan_300.value, - chart_color_gold_300.value, - chart_color_orange_300.value, - chart_color_blue_100.value, - chart_color_green_500.value, - chart_color_cyan_100.value, - chart_color_gold_100.value, - chart_color_orange_500.value, - chart_color_blue_500.value, - chart_color_green_100.value, - chart_color_cyan_500.value, - chart_color_gold_500.value, - chart_color_orange_100.value, - chart_color_blue_200.value, - chart_color_green_400.value, - chart_color_cyan_200.value, - chart_color_gold_200.value, - chart_color_orange_400.value, - chart_color_blue_400.value, - chart_color_green_200.value, - chart_color_cyan_400.value, - chart_color_gold_400.value, - chart_color_orange_200.value -]; - -export const LightMultiColorOrderedTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/multi-color-unordered-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/multi-color-unordered-theme.ts deleted file mode 100644 index 98028fbcf32..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/multi-color-unordered-theme.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_blue_100 from '@patternfly/react-tokens/dist/esm/chart_color_blue_100'; -import chart_color_blue_200 from '@patternfly/react-tokens/dist/esm/chart_color_blue_200'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_blue_400 from '@patternfly/react-tokens/dist/esm/chart_color_blue_400'; -import chart_color_blue_500 from '@patternfly/react-tokens/dist/esm/chart_color_blue_500'; -import chart_color_green_100 from '@patternfly/react-tokens/dist/esm/chart_color_green_100'; -import chart_color_green_200 from '@patternfly/react-tokens/dist/esm/chart_color_green_200'; -import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; -import chart_color_green_400 from '@patternfly/react-tokens/dist/esm/chart_color_green_400'; -import chart_color_green_500 from '@patternfly/react-tokens/dist/esm/chart_color_green_500'; -import chart_color_cyan_100 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_100'; -import chart_color_cyan_200 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_200'; -import chart_color_cyan_300 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_300'; -import chart_color_cyan_400 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_400'; -import chart_color_cyan_500 from '@patternfly/react-tokens/dist/esm/chart_color_cyan_500'; -import chart_color_purple_100 from '@patternfly/react-tokens/dist/esm/chart_color_purple_100'; -import chart_color_purple_200 from '@patternfly/react-tokens/dist/esm/chart_color_purple_200'; -import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; -import chart_color_purple_400 from '@patternfly/react-tokens/dist/esm/chart_color_purple_400'; -import chart_color_purple_500 from '@patternfly/react-tokens/dist/esm/chart_color_purple_500'; -import chart_color_gold_100 from '@patternfly/react-tokens/dist/esm/chart_color_gold_100'; -import chart_color_gold_200 from '@patternfly/react-tokens/dist/esm/chart_color_gold_200'; -import chart_color_gold_300 from '@patternfly/react-tokens/dist/esm/chart_color_gold_300'; -import chart_color_gold_400 from '@patternfly/react-tokens/dist/esm/chart_color_gold_400'; -import chart_color_gold_500 from '@patternfly/react-tokens/dist/esm/chart_color_gold_500'; -import chart_color_orange_100 from '@patternfly/react-tokens/dist/esm/chart_color_orange_100'; -import chart_color_orange_200 from '@patternfly/react-tokens/dist/esm/chart_color_orange_200'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; -import chart_color_orange_400 from '@patternfly/react-tokens/dist/esm/chart_color_orange_400'; -import chart_color_orange_500 from '@patternfly/react-tokens/dist/esm/chart_color_orange_500'; -import chart_color_black_100 from '@patternfly/react-tokens/dist/esm/chart_color_black_100'; -import chart_color_black_200 from '@patternfly/react-tokens/dist/esm/chart_color_black_200'; -import chart_color_black_300 from '@patternfly/react-tokens/dist/esm/chart_color_black_300'; -import chart_color_black_400 from '@patternfly/react-tokens/dist/esm/chart_color_black_400'; -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; -import { ColorTheme } from '../color-theme'; - -// The color order below improves the color contrast in unordered charts; area & line -// See https://github.com/patternfly/patternfly-next/issues/1551 -const COLOR_SCALE = [ - chart_color_blue_300.value, - chart_color_gold_300.value, - chart_color_green_300.value, - chart_color_purple_300.value, - chart_color_orange_300.value, - chart_color_cyan_300.value, - chart_color_black_300.value, - chart_color_blue_100.value, - chart_color_gold_500.value, - chart_color_green_100.value, - chart_color_purple_500.value, - chart_color_orange_100.value, - chart_color_cyan_500.value, - chart_color_black_100.value, - chart_color_blue_500.value, - chart_color_gold_100.value, - chart_color_green_500.value, - chart_color_purple_100.value, - chart_color_orange_500.value, - chart_color_cyan_100.value, - chart_color_black_500.value, - chart_color_blue_200.value, - chart_color_gold_400.value, - chart_color_green_200.value, - chart_color_purple_400.value, - chart_color_orange_200.value, - chart_color_cyan_400.value, - chart_color_black_200.value, - chart_color_blue_400.value, - chart_color_gold_200.value, - chart_color_green_400.value, - chart_color_purple_200.value, - chart_color_orange_400.value, - chart_color_cyan_200.value, - chart_color_black_400.value -]; - -export const LightMultiColorUnorderedTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/orange-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/orange-color-theme.ts deleted file mode 100644 index fe0d018188c..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/orange-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_orange_100 from '@patternfly/react-tokens/dist/esm/chart_color_orange_100'; -import chart_color_orange_200 from '@patternfly/react-tokens/dist/esm/chart_color_orange_200'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; -import chart_color_orange_400 from '@patternfly/react-tokens/dist/esm/chart_color_orange_400'; -import chart_color_orange_500 from '@patternfly/react-tokens/dist/esm/chart_color_orange_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_orange_300.value, - chart_color_orange_100.value, - chart_color_orange_500.value, - chart_color_orange_200.value, - chart_color_orange_400.value -]; - -export const LightOrangeColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/light/purple-color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/light/purple-color-theme.ts deleted file mode 100644 index 715be1f8576..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/light/purple-color-theme.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_purple_100 from '@patternfly/react-tokens/dist/esm/chart_color_purple_100'; -import chart_color_purple_200 from '@patternfly/react-tokens/dist/esm/chart_color_purple_200'; -import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; -import chart_color_purple_400 from '@patternfly/react-tokens/dist/esm/chart_color_purple_400'; -import chart_color_purple_500 from '@patternfly/react-tokens/dist/esm/chart_color_purple_500'; -import { ColorTheme } from '../color-theme'; - -// Color scale -// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit -const COLOR_SCALE = [ - chart_color_purple_300.value, - chart_color_purple_100.value, - chart_color_purple_500.value, - chart_color_purple_200.value, - chart_color_purple_400.value -]; - -export const LightPurpleColorTheme = ColorTheme({ - COLOR_SCALE -}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/threshold-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/threshold-theme.ts deleted file mode 100644 index 736d7c07368..00000000000 --- a/packages/react-charts/src/components/ChartTheme/themes/threshold-theme.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable camelcase */ -import chart_threshold_stroke_dash_array from '@patternfly/react-tokens/dist/esm/chart_threshold_stroke_dash_array'; -import chart_threshold_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_threshold_stroke_Width'; - -// Threshold theme -export const ThresholdTheme = { - line: { - style: { - data: { - strokeDasharray: chart_threshold_stroke_dash_array.value, - strokeWidth: chart_threshold_stroke_Width.value - } - } - } -}; diff --git a/packages/react-charts/src/components/ChartThreshold/ChartThreshold.test.tsx b/packages/react-charts/src/components/ChartThreshold/ChartThreshold.test.tsx deleted file mode 100644 index 18e3709bb1d..00000000000 --- a/packages/react-charts/src/components/ChartThreshold/ChartThreshold.test.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Chart } from '../Chart'; -import { ChartGroup } from '../ChartGroup'; -import { ChartThreshold } from './ChartThreshold'; - -Object.values([true, false]).forEach(() => { - test('ChartThreshold', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders component data', () => { - const data = [ - { name: 'Birds Threshold', x: 0, y: 2 }, - { name: 'Birds Threshold', x: 2, y: 2 }, - { name: 'Birds Threshold', x: 2, y: 3 }, - { name: 'Birds Threshold', x: 5, y: 3 } - ]; - const view = shallow( - - - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartThreshold/__snapshots__/ChartThreshold.test.tsx.snap b/packages/react-charts/src/components/ChartThreshold/__snapshots__/ChartThreshold.test.tsx.snap deleted file mode 100644 index a1292d30c2e..00000000000 --- a/packages/react-charts/src/components/ChartThreshold/__snapshots__/ChartThreshold.test.tsx.snap +++ /dev/null @@ -1,4179 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartThreshold 1`] = ` - -`; - -exports[`ChartThreshold 2`] = ` - -`; - -exports[`renders component data 1`] = ` -} - rectComponent={} - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - - } - defaultAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - fixLabelOverlap={false} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - defaultPolarAxes={ - Object { - "dependent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - dependentAxis={true} - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - "independent": } - role="presentation" - shapeRendering="auto" - /> - } - axisLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - circularAxisComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - circularGridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - containerComponent={ - } - portalZIndex={99} - responsive={true} - role="img" - /> - } - endAngle={360} - gridComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={ - - } - labelPlacement="parallel" - standalone={true} - startAngle={0} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 25, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - }, - "tickLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 1, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "bar": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "padding": 8, - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#252525", - "strokeWidth": 1, - }, - "minLabels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#969696", - "padding": 8, - }, - "q1Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#969696", - "padding": 8, - }, - "q3Labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 3, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#252525", - "positive": "#ffffff", - }, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "histogram": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#969696", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "gutter": 10, - "orientation": "vertical", - "style": Object { - "data": Object { - "type": "circle", - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "#252525", - "strokeWidth": 2, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 400, - "padding": 50, - "style": Object { - "data": Object { - "padding": 10, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 20, - "stroke": "transparent", - }, - }, - "width": 400, - }, - "scatter": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#252525", - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 5, - "flyoutPadding": 5, - "flyoutStyle": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "pointerLength": 10, - "style": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 0, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#252525", - "#525252", - "#737373", - "#969696", - "#bdbdbd", - "#d9d9d9", - "#f0f0f0", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - "stroke": "#252525", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#252525", - "fontFamily": "'Gill Sans', 'Seravek', 'Trebuchet MS', sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 5, - "pointerEvents": "none", - "stroke": "transparent", - }, - }, - "width": 450, - }, - } - } - tickComponent={ - } - role="presentation" - shapeRendering="auto" - /> - } - tickLabelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - />, - } - } - groupComponent={} - height={200} - minDomain={ - Object { - "y": 0, - } - } - padding={ - Object { - "bottom": 50, - "left": 50, - "right": 50, - "top": 50, - } - } - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - - -`; diff --git a/packages/react-charts/src/components/ChartThreshold/examples/ChartThreshold.md b/packages/react-charts/src/components/ChartThreshold/examples/ChartThreshold.md deleted file mode 100644 index 5dfd600ec8c..00000000000 --- a/packages/react-charts/src/components/ChartThreshold/examples/ChartThreshold.md +++ /dev/null @@ -1,197 +0,0 @@ ---- -id: Threshold chart -section: charts -propComponents: [ - 'Chart', - 'ChartAxis', - 'ChartGroup', - 'ChartThreshold', - 'ChartVoronoiContainer' -] -hideDarkMode: true ---- - -import { - Chart, - ChartArea, - ChartAxis, - ChartGroup, - ChartLegend, - ChartThreshold, - ChartThemeColor, - ChartThemeVariant, - ChartVoronoiContainer, - getResizeObserver -} from '@patternfly/react-charts'; -import '@patternfly/patternfly/patternfly-charts.css'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; - - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, - along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -## Examples -### Multi-color (unordered) with responsive container -```js -import React from 'react'; -import { - Chart, - ChartArea, - ChartAxis, - ChartLegend, - ChartGroup, - ChartThreshold, - ChartThemeColor, - ChartVoronoiContainer, - getResizeObserver -} from '@patternfly/react-charts'; -import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; -import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; - -class MultiColorChart extends React.Component { - constructor(props) { - super(props); - this.containerRef = React.createRef(); - this.observer = () => {}; - this.state = { - width: 0 - }; - this.handleResize = () => { - if (this.containerRef.current && this.containerRef.current.clientWidth) { - this.setState({ width: this.containerRef.current.clientWidth }); - } - }; - } - - componentDidMount() { - this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - this.handleResize(); - } - - componentWillUnmount() { - this.observer(); - } - - render() { - const { width } = this.state; - const itemsPerRow = width > 650 ? 4 : 2; - - return ( -
    -
    - `${datum.name}: ${datum.y}`} - constrainToVisibleArea - /> - } - legendPosition="bottom-left" - legendComponent={ - - } - height={250} - padding={{ - bottom: 100, // Adjusted to accomodate legend - left: 50, - right: 50, - top: 50 - }} - maxDomain={{ y: 9 }} - themeColor={ChartThemeColor.multiUnordered} - width={width} - > - - - - - - - - - -
    -
    - ); - } -} -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- `ChartLegend` may be used as a standalone component, instead of using `legendData` - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) - - For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) - - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) - - For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) - - For `ChartLegend` props, see [VictoryLegend](https://formidable.com/open-source/victory/docs/victory-legend) - - For `ChartThreshold` props, see [VictoryLine](https://formidable.com/open-source/victory/docs/victory-line) - - For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/components/ChartThreshold/index.ts b/packages/react-charts/src/components/ChartThreshold/index.ts deleted file mode 100644 index 908ff59e0d9..00000000000 --- a/packages/react-charts/src/components/ChartThreshold/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartThreshold'; diff --git a/packages/react-charts/src/components/ChartTooltip/ChartTooltip.test.tsx b/packages/react-charts/src/components/ChartTooltip/ChartTooltip.test.tsx deleted file mode 100644 index 5d433ac04eb..00000000000 --- a/packages/react-charts/src/components/ChartTooltip/ChartTooltip.test.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartArea } from '../ChartArea'; -import { ChartGroup } from '../ChartGroup'; -import { ChartVoronoiContainer } from '../ChartVoronoiContainer'; -import { ChartTooltip } from './ChartTooltip'; - -Object.values([true, false]).forEach(() => { - test('ChartTooltip', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('allows tooltip via container component', () => { - const view = shallow( - 'y: ' + point.y} />} - height={200} - width={200} - > - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap b/packages/react-charts/src/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap deleted file mode 100644 index a453af82a84..00000000000 --- a/packages/react-charts/src/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap +++ /dev/null @@ -1,2844 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartTooltip 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - - } - renderInPortal={true} - text="This is a tooltip" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`ChartTooltip 2`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - - } - renderInPortal={true} - text="This is a tooltip" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } -/> -`; - -exports[`allows tooltip via container component 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - renderInPortal={true} - /> - } - labels={[Function]} - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - voronoiPadding={5} - /> - } - groupComponent={} - height={200} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - -`; diff --git a/packages/react-charts/src/components/ChartTooltip/examples/ChartTooltip.md b/packages/react-charts/src/components/ChartTooltip/examples/ChartTooltip.md deleted file mode 100644 index d08d54d5f12..00000000000 --- a/packages/react-charts/src/components/ChartTooltip/examples/ChartTooltip.md +++ /dev/null @@ -1,751 +0,0 @@ ---- -id: Tooltip chart -section: charts -propComponents: ['ChartTooltip'] -hideDarkMode: true ---- - -import { - Chart, - ChartArea, - ChartAxis, - ChartBar, - ChartContainer, - ChartCursorFlyout, - ChartCursorTooltip, - ChartDonut, - ChartDonutThreshold, - ChartDonutUtilization, - ChartGroup, - ChartLabel, - ChartLegend, - ChartLegendTooltip, - ChartLine, - ChartPie, - ChartPoint, - ChartStack, - ChartThemeColor, - ChartThemeVariant, - ChartTooltip, - ChartVoronoiContainer, - createContainer, - getCustomTheme -} from '@patternfly/react-charts'; -import './chart-tooltip.css'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -## Examples -### Voronoi container - -This demonstrates how to use a voronoi container to display tooltips. - -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // Required for mix-blend-mode CSS property - -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]} - legendOrientation="vertical" - legendPosition="right" - height={200} - maxDomain={{y: 9}} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - width={800} - > - - - - - - - - -
    -``` - -### Combined cursor and voronoi containers - -This demonstrates how to combine cursor and voronoi containers to display tooltips along with a vertical cursor. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, ChartTooltip, ChartVoronoiContainer, createContainer } from '@patternfly/react-charts'; - -class CombinedCursorVoronoiContainer extends React.Component { - render() { - // Note: Container order is important - const CursorVoronoiContainer = createContainer("voronoi", "cursor"); - - return ( -
    - `${datum.name}: ${datum.y}`} - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - } - legendData={[{ name: 'Cats' }, { name: 'Dogs', symbol: { type: 'dash' } }, { name: 'Birds' }, { name: 'Mice' }]} - legendPosition="bottom" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.orange} - width={450} - > - - - - - - - - - -
    - ); - } -} -``` - -### Embedded legend - -This demonstrates how to embed a legend within a tooltip. Combining cursor and voronoi containers is required to display tooltips with a vertical cursor. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLegendTooltip, ChartLine, ChartThemeColor, ChartVoronoiContainer, createContainer } from '@patternfly/react-charts'; - -import chart_voronoi_labels_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Fill'; -import global_FontWeight_bold from '@patternfly/react-tokens/dist/esm/global_FontWeight_bold'; - -class EmbeddedLegend extends React.Component { - render() { - // Note: Container order is important - const CursorVoronoiContainer = createContainer("voronoi", "cursor"); - const legendData = [{ childName: 'cats', name: 'Cats' }, { childName: 'dogs', name: 'Dogs', symbol: { type: 'dash' }}, { childName: 'birds', name: 'Birds' }, { childName: 'mice', name: 'Mice' }]; - - return ( -
    - `${datum.y !== null ? datum.y : 'no data'}`} - labelComponent={ datum.x}/>} - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - } - legendData={legendData} - legendPosition="bottom" - height={275} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50 - }} - themeColor={ChartThemeColor.green} - width={450} - > - - - - - - - - - -
    - ); - } -} -``` - -### Embedded HTML - -This demonstrates how to embed HTML within a tooltip. Combining cursor and voronoi containers is required to display tooltips with a vertical cursor. - -```js -import React from 'react'; -import { Chart, ChartArea, ChartAxis, ChartCursorFlyout, ChartCursorTooltip, ChartGroup, ChartPoint, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; -// import '@patternfly/patternfly/patternfly-charts.css'; // Required for mix-blend-mode CSS property - -class EmbeddedHtml extends React.Component { - constructor(props) { - super(props); - this.baseStyles = { - color: '#f0f0f0', - fontFamily: 'RedHatText, Overpass, overpass, helvetica, arial, sans-serif', - fontSize: '14px' - }; - } - - render() { - // Note: Container order is important - const CursorVoronoiContainer = createContainer("voronoi", "cursor"); - const legendData = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]; - - // Custom HTML component to create a legend layout - const HtmlLegendContent = ({datum, legendData, text, theme, title, x, y, ...rest}) => ( - - - - - - - - - - {text.map((val, index) => ( - - - - - - ))} - -
    {title(datum)}
    - - {} - - {legendData[index].name}{val}
    -
    -
    - ); - - return ( -
    - `${datum.y}`} - labelComponent={ - width > center.x + flyoutWidth + 10 ? offset : -offset}} - flyout={} - flyoutHeight={110} - flyoutWidth={125} - labelComponent={ datum.x} />} - /> - } - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={50} - /> - } - legendData={legendData} - legendPosition="bottom-left" - height={225} - padding={{ - bottom: 75, // Adjusted to accommodate legend - left: 50, - right: 50, - top: 50, - }} - maxDomain={{y: 9}} - themeColor={ChartThemeColor.multiUnordered} - width={650} - > - - - - - - - - -
    - ); - } -} -``` - -### Data label - -This demonstrates an alternate way of applying tooltips using data labels. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartBar, ChartStack, ChartThemeColor, ChartTooltip } from '@patternfly/react-charts'; - -
    - - - - - } - /> - } - /> - } - /> - } - /> - - -
    -``` - -### Legend - -This demonstrates an approach for applying tooltips to a legend using a custom label component. - -```js -import React from 'react'; -import { ChartLabel, ChartLegend, ChartPie, ChartThemeColor } from '@patternfly/react-charts'; -import { Tooltip } from '@patternfly/react-core'; - -class TooltipPieChart extends React.Component { - constructor(props) { - super(props); - - // Custom legend label compoenent - this.LegendLabel = ({datum, ...rest}) => ( - - - - ); - - // Custom legend component - this.getLegend = (legendData) => ( - } - /> - ); - } - - render() { - return ( -
    - `${datum.x}: ${datum.y}`} - legendComponent={this.getLegend([ - { name: 'Cats: 35' }, - { name: 'Dogs: 55' }, - { name: 'Birds: 10' } - ])} - legendPosition="bottom" - padding={{ - bottom: 65, - left: 20, - right: 20, - top: 20 - }} - themeColor={ChartThemeColor.multiOrdered} - width={300} - /> -
    - ); - } -} -``` - -### Left aligned - -This demonstrates how to customize tooltip label alignment using theme properties. - -```js -import React from 'react'; -import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, ChartThemeVariant, ChartVoronoiContainer, getCustomTheme } from '@patternfly/react-charts'; - -class TooltipThemeChart extends React.Component { - constructor(props) { - super(props); - - // Victory theme properties only - this.themeProps = { - voronoi: { - style: { - labels: { - textAnchor: 'start' // Align tooltip labels left - } - } - } - }; - - // Applies theme color and variant to base theme - this.myCustomTheme = getCustomTheme( - ChartThemeColor.default, - ChartThemeVariant.default, - this.themeProps - ); - } - - render() { - return ( -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea voronoiDimension="x"/>} - legendData={[{ name: 'Cats' }, { name: 'Dogs', symbol: { type: 'dash' } }, { name: 'Birds' }, { name: 'Mice' }]} - legendOrientation="vertical" - legendPosition="right" - height={250} - maxDomain={{y: 10}} - minDomain={{y: 0}} - padding={{ - bottom: 50, - left: 50, - right: 200, // Adjusted to accommodate legend - top: 50 - }} - theme={this.myCustomTheme} - width={600} - > - - - - - - - - - -
    - ); - } -} -``` - -### CSS overflow - -This demonstrates an alternate way of applying tooltips using CSS overflow instead of constrainToVisibleArea. - -```js -import React from 'react'; -import { ChartArea, ChartContainer, ChartGroup, ChartLabel, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    -
    - `${datum.name}: ${datum.y}`} />} - height={100} - maxDomain={{y: 9}} - padding={0} - themeColor={ChartThemeColor.green} - width={400} - > - - -
    - - - -
    -``` - -### Wrapped chart - -This demonstrates an alternate way of applying tooltips by wrapping charts with the Tooltip component. - -```js -import React from 'react'; -import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; -import { Button, Tooltip, TooltipPosition } from '@patternfly/react-core'; - -class TooltipChart extends React.Component { - constructor(props) { - super(props); - this.state = { - isVisible: false - }; - this.showTooltip = () => { - this.setState({ isVisible: !this.state.isVisible }); - }; - } - - render() { - const { isVisible } = this.state; - - return ( -
    -
    - My custom tooltip
    } isVisible={isVisible} position={TooltipPosition.right} trigger="manual"> - null} - > - null} - subTitle="of 100 GBps" - title="45%" - /> - - -
    -
    - -
    - - ); - } -} -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `ChartTooltip` props, see [VictoryTooltip](https://formidable.com/open-source/victory/docs/victory-tooltip) diff --git a/packages/react-charts/src/components/ChartTooltip/index.ts b/packages/react-charts/src/components/ChartTooltip/index.ts deleted file mode 100644 index 00b811322db..00000000000 --- a/packages/react-charts/src/components/ChartTooltip/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartTooltip'; diff --git a/packages/react-charts/src/components/ChartUtils/chart-container.tsx b/packages/react-charts/src/components/ChartUtils/chart-container.tsx deleted file mode 100644 index 56a25bf7d10..00000000000 --- a/packages/react-charts/src/components/ChartUtils/chart-container.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; -import { ContainerType, createContainer as victoryCreateContainer } from 'victory-create-container'; -import { ChartCursorTooltip } from '../ChartCursorTooltip'; -import { ChartLabel } from '../ChartLabel'; - -/** - * Makes a container component with multiple behaviors. It allows you to effectively combine any two - * containers of type 'brush', 'cursor', 'selection', 'voronoi', or 'zoom'. Default container props are applied to - * support the PatternFly theme. - * - * Each behavior must be one of the following strings: 'brush', 'cursor', 'selection', 'voronoi', and 'zoom'. The - * resulting container uses the events from both behaviors. For example, if both behaviors use the click event (like - * zoom and selection) the combined container will trigger both behaviors' events on each click. - * - * Note: Order of the behaviors matters in a few cases. It is recommended to use 'zoom' before any other behaviors: for - * example, createContainer('zoom', 'voronoi') instead of createContainer('voronoi', 'zoom'). - * - * See https://formidable.com/open-source/victory/docs/create-container - * - * @param {string} behaviorA 'brush', 'cursor', 'selection', 'voronoi', or 'zoom' - * @param {string} behaviorB 'brush', 'cursor', 'selection', 'voronoi', or 'zoom' - */ -export const createContainer = (behaviorA: ContainerType, behaviorB: ContainerType) => { - const container: any = victoryCreateContainer(behaviorA, behaviorB); - const isCursor = behaviorA === 'cursor' || behaviorB === 'cursor'; - const isVoronoi = behaviorA === 'voronoi' || behaviorB === 'voronoi'; - - if (isCursor) { - container.defaultProps.cursorLabelComponent = ; - } - if (isVoronoi) { - container.defaultProps.labelComponent = ; - } - return container; -}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-helpers.ts b/packages/react-charts/src/components/ChartUtils/chart-helpers.ts deleted file mode 100644 index c2cca7a1e91..00000000000 --- a/packages/react-charts/src/components/ChartUtils/chart-helpers.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Misc util functions - -interface ChartClassNameInterface { - className?: string; -} - -// Copied from exenv -export const canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); - -// Returns the class name that will be applied to the outer-most div rendered by the chart's container -export const getClassName = ({ className }: ChartClassNameInterface) => { - let cleanClassName; - - // Workaround for VictoryContainer class name - if (className) { - cleanClassName = className - .replace(/VictoryContainer/g, '') - .replace(/pf-c-chart/g, '') - .replace(/\s+/g, ' ') - .trim(); - } - return cleanClassName && cleanClassName.length ? `pf-c-chart ${cleanClassName}` : 'pf-c-chart'; -}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-legend.ts b/packages/react-charts/src/components/ChartUtils/chart-legend.ts deleted file mode 100644 index 0f7efa49b3c..00000000000 --- a/packages/react-charts/src/components/ChartUtils/chart-legend.ts +++ /dev/null @@ -1,432 +0,0 @@ -import defaults from 'lodash/defaults'; -import { Helpers, PaddingProps, TextSize } from 'victory-core'; -import { VictoryLegend } from 'victory-legend'; -import { ChartLegendOrientation, ChartLegendPosition, ChartLegendProps } from '../ChartLegend'; -import { ChartCommonStyles, ChartThemeDefinition } from '../ChartTheme'; -import { getPieOrigin } from './chart-origin'; -import * as React from 'react'; - -interface ChartLegendInterface { - allowWrap?: boolean; // Allow legend items to wrap to the next line - chartType?: string; // The type of chart (e.g., pie) to lookup for props - dx?: number; // Horizontal shift from the x coordinate - dy?: number; // Vertical shift from the x coordinate - height: number; // Overall height of SVG - legendComponent: React.ReactElement; // The base legend component to render - orientation?: 'horizontal' | 'vertical'; // Orientation of legend - padding: PaddingProps; // Chart padding - position: 'bottom' | 'bottom-left' | 'right'; // The legend position - theme: ChartThemeDefinition; // The theme that will be applied to the chart - width: number; // Overall width of SVG -} - -interface ChartLegendDimensionsInterface { - legendData: any[]; // The legend data used to determine width - legendOrientation: 'horizontal' | 'vertical'; // Orientation of legend - legendProps: ChartLegendProps; // Legend properties - theme: ChartThemeDefinition; // The theme that will be applied to the chart -} - -interface ChartLegendPositionInterface { - chartType?: string; // The type of chart (e.g., pie) to lookup for props - dx?: number; // Horizontal shift from the x coordinate - dy?: number; // Vertical shift from the x coordinate - height?: number; // Overall height of SVG - legendData: any[]; // The legend data used to determine width - legendOrientation: 'horizontal' | 'vertical'; // Orientation of legend - legendPosition: 'bottom' | 'bottom-left' | 'right'; // Position of legend - legendProps: any; // The legend props used to determine width - padding?: PaddingProps; // Chart padding - theme: ChartThemeDefinition; // The theme that will be applied to the chart - width?: number; // Overall width of SVG -} - -interface ChartLegendTextMaxSizeInterface { - legendData: any[]; // The legend data used to determine width - theme: ChartThemeDefinition; // The theme that will be applied to the chart -} - -// Returns a legend which has been positioned per the given chart properties -export const getComputedLegend = ({ - allowWrap = true, - chartType = 'chart', - dx = 0, - dy = 0, - height, - legendComponent, - padding, - position = ChartCommonStyles.legend.position as ChartLegendPosition, - theme, - width, - - // destructure last - orientation = theme.legend.orientation as ChartLegendOrientation -}: ChartLegendInterface) => { - // Get the number of legend items per row - const legendItemsProps = legendComponent.props ? legendComponent.props : {}; - const legendItemsPerRow = allowWrap - ? getLegendItemsPerRow({ - chartType, - dx, - height, - legendData: legendItemsProps.data, - legendOrientation: legendItemsProps.legendOrientation ? legendItemsProps.legendOrientation : orientation, - legendPosition: position, - legendProps: legendItemsProps, - padding, - theme, - width - }) - : undefined; - - // Include new itemsPerRow prop when determining x and y position - const legendPositionProps = defaults({}, legendComponent.props, { - itemsPerRow: legendItemsPerRow - }); - - const legendX = getLegendX({ - chartType, - dx, - height, - legendData: legendPositionProps.data, - legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation, - legendPosition: position, - legendProps: legendPositionProps, - padding, - theme, - width - }); - - const legendY = getLegendY({ - chartType, - dy, - height, - legendData: legendPositionProps.data, - legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation, - legendProps: legendPositionProps, - legendPosition: position, - padding, - theme, - width - }); - - // Clone legend with updated props - const legendProps = defaults({}, legendComponent.props, { - itemsPerRow: legendItemsPerRow, - orientation, - standalone: false, - theme, - x: legendX > 0 ? legendX : 0, - y: legendY > 0 ? legendY : 0 - }); - return React.cloneElement(legendComponent, legendProps); -}; - -// Returns legend dimensions -export const getLegendDimensions = ({ - legendData, - legendOrientation, - legendProps, - theme -}: ChartLegendDimensionsInterface) => { - if (legendData || legendProps.data) { - return (VictoryLegend as any).getDimensions({ - data: legendData, - orientation: legendOrientation, - theme, - ...legendProps // override above - }); - } - return {}; -}; - -// Returns true if the legend is smaller than its container -export const doesLegendFit = ({ - dx = 0, - height, - legendPosition, - legendData, - legendOrientation, - legendProps, - padding, - theme, - width -}: ChartLegendPositionInterface) => { - const { left, right } = Helpers.getPadding({ padding }); - const chartSize = { - height, // Fixed size - width: width - left - right - }; - const legendDimensions = getLegendDimensions({ - legendData, - legendOrientation, - legendProps, - theme - }); - - let occupiedWidth = 0; - switch (legendPosition) { - case 'bottom-left': - occupiedWidth = left + dx; - break; - case 'right': - occupiedWidth = chartSize.width + ChartCommonStyles.legend.margin + left + dx; - break; - default: - occupiedWidth = dx; - break; - } - return width - occupiedWidth > legendDimensions.width; -}; - -// Returns the number of legend items per row -export const getLegendItemsPerRow = ({ - dx, - height, - legendPosition, - legendData, - legendOrientation, - legendProps, - padding, - theme, - width -}: ChartLegendPositionInterface) => { - let itemsPerRow = legendData ? legendData.length : 0; - for (let i = itemsPerRow; i > 0; i--) { - const fits = doesLegendFit({ - dx, - height, - legendPosition, - legendData, - legendOrientation, - legendProps: { - ...legendProps, - itemsPerRow: i - }, - padding, - theme, - width - }); - if (fits) { - itemsPerRow = i; - break; - } - } - return itemsPerRow; -}; - -// Returns x coordinate for legend -export const getLegendX = ({ chartType, ...rest }: ChartLegendPositionInterface) => - chartType === 'pie' ? getPieLegendX(rest) : getChartLegendX(rest); - -// Returns y coordinate for legend -export const getLegendY = ({ chartType, ...rest }: ChartLegendPositionInterface) => { - switch (chartType) { - case 'pie': - return getPieLegendY(rest); - case 'bullet': - return getBulletLegendY(rest); - default: - return getChartLegendY(rest); - } -}; - -// Returns y coordinate for bullet legends -export const getBulletLegendY = ({ - dy = 0, - height, - legendPosition, - legendData, - legendOrientation, - legendProps, - padding, - theme, - width -}: ChartLegendPositionInterface) => { - const { left, right } = Helpers.getPadding({ padding }); - const chartSize = { - height, // Fixed size - width: width - left - right - }; - - switch (legendPosition) { - case 'bottom': - case 'bottom-left': - return chartSize.height + ChartCommonStyles.legend.margin + dy; - case 'right': { - // Legend height with padding - const legendDimensions = getLegendDimensions({ - legendData, - legendOrientation, - legendProps, - theme - }); - const legendPadding = (legendDataArr: any[]) => (legendDataArr && legendDataArr.length > 0 ? 17 : 0); - return (chartSize.height - legendDimensions.height) / 2 + legendPadding(legendData); - } - default: - return dy; - } -}; - -// Returns x coordinate for chart legends -export const getChartLegendX = ({ - dx = 0, - height, - legendData, - legendOrientation, - legendPosition, - legendProps, - padding, - theme, - width -}: ChartLegendPositionInterface) => { - const { top, bottom, left, right } = Helpers.getPadding({ padding }); - const chartSize = { - height: Math.abs(height - (bottom + top)), - width: Math.abs(width - (left + right)) - }; - const legendDimensions = getLegendDimensions({ - legendData, - legendOrientation, - legendProps, - theme - }); - - switch (legendPosition) { - case 'bottom': - return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx; - case 'bottom-left': - return left + dx; - case 'right': - return chartSize.width + ChartCommonStyles.legend.margin + left + dx; - default: - return dx; - } -}; - -// Returns y coordinate for chart legends -export const getChartLegendY = ({ - dy = 0, - height, - legendPosition, - legendData, - legendOrientation, - legendProps, - padding, - theme, - width -}: ChartLegendPositionInterface) => { - const { top, bottom, left, right } = Helpers.getPadding({ padding }); - const chartSize = { - height: Math.abs(height - (bottom + top)), - width: Math.abs(width - (left + right)) - }; - - switch (legendPosition) { - case 'bottom': - case 'bottom-left': - return chartSize.height + ChartCommonStyles.legend.margin * 2 + top + dy; - case 'right': { - // Legend height with padding - const legendDimensions = getLegendDimensions({ - legendData, - legendOrientation, - legendProps, - theme - }); - const originX = chartSize.height / 2 + top; - const legendPadding = (legendDataArr: any[]) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0); - return originX - legendDimensions.height / 2 + legendPadding(legendData); - } - default: - return dy; - } -}; - -// Returns x coordinate for pie legends -export const getPieLegendX = ({ - dx = 0, - height, - legendData, - legendOrientation, - legendPosition, - legendProps, - padding, - theme, - width -}: ChartLegendPositionInterface) => { - const origin = getPieOrigin({ height, padding, width }); - const radius = Helpers.getRadius({ height, width, padding }); - const legendDimensions = getLegendDimensions({ - legendData, - legendOrientation, - legendProps, - theme - }); - - switch (legendPosition) { - case 'bottom': - return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx; - case 'right': - return origin.x + ChartCommonStyles.label.margin + dx + radius; - default: - return dx; - } -}; - -// Returns y coordinate for pie legends -export const getPieLegendY = ({ - dy = 0, - height, - legendPosition, - legendData, - legendOrientation, - legendProps, - padding, - theme, - width -}: ChartLegendPositionInterface) => { - const origin = getPieOrigin({ height, padding, width }); - const radius = Helpers.getRadius({ height, width, padding }); - - switch (legendPosition) { - case 'bottom': - return origin.y + ChartCommonStyles.legend.margin + radius + dy; - case 'right': { - // Legend height with padding - const legendDimensions = getLegendDimensions({ - legendData, - legendOrientation, - legendProps, - theme - }); - const legendPadding = (legendDataArr: any[]) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0); - return origin.y - legendDimensions.height / 2 + legendPadding(legendData); - } - default: - return dy; - } -}; - -// Returns an approximation of longest text width based on legend styles -export const getMaxLegendTextSize = ({ legendData, theme }: ChartLegendTextMaxSizeInterface) => { - const style: any = theme && theme.legend && theme.legend.style ? theme.legend.style.labels : undefined; - if (!(legendData && legendData.length)) { - return 0; - } - - let result = ''; - legendData.forEach(data => { - if (data.name && data.name.length > result.length) { - result = data.name; - } - }); - - // The approximateTextSize function returns height and width, but Victory incorrectly typed it as number - const adjustedTextSize: any = TextSize.approximateTextSize(result, { - ...style - }); - - return adjustedTextSize.width; -}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-origin.ts b/packages/react-charts/src/components/ChartUtils/chart-origin.ts deleted file mode 100644 index bcb6b96c758..00000000000 --- a/packages/react-charts/src/components/ChartUtils/chart-origin.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Helpers } from 'victory-core'; - -interface ChartPieOriginInterface { - height: number; // Chart height - padding: any; // Chart padding - width: number; // Chart width -} - -// Returns the origin for pie based charts. For example, something with a radius such as pie, donut, donut utilization, -// and donut threshold. -export const getPieOrigin = ({ height, padding, width }: ChartPieOriginInterface) => { - const { top, bottom, left, right } = Helpers.getPadding({ padding }); - const radius = Helpers.getRadius({ height, width, padding }); - const offsetX = (width - radius * 2 - left - right) / 2; - const offsetY = (height - radius * 2 - top - bottom) / 2; - return { - x: radius + left + offsetX, - y: radius + top + offsetY - }; -}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-resize.tsx b/packages/react-charts/src/components/ChartUtils/chart-resize.tsx deleted file mode 100644 index 10aa5ca4b24..00000000000 --- a/packages/react-charts/src/components/ChartUtils/chart-resize.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { canUseDOM } from './chart-helpers'; - -/** - * This function creates a ResizeObserver used to handle resize events for the given containerRef. If ResizeObserver - * or the given containerRef are not available, a window resize event listener is used by default. - * - * Example 1: - * - * private containerRef = React.createRef(); - * private observer: any = () => {}; - * - * public componentDidMount() { - * this.observer = getResizeObserver(this.containerRef.current, this.handleResize); - * } - * - * public componentWillUnmount() { - * this.observer(); - * } - * - * private handleResize = () => { - * if (this.containerRef.current && this.containerRef.current.clientWidth) { - * this.setState({ width: this.containerRef.current.clientWidth }); - * } - * }; - * - * public render() { - * return ( - *
    - * - *
    - * ); - * } - * - * Example 2: - * - * private inputRef = React.createRef(); - * private observer: any = () => {}; - * - * public componentDidMount() { - * this.observer = getResizeObserver(this.inputRef.current, this.handleResize); - * } - * - * public componentWillUnmount() { - * this.observer(); - * } - * - * private handleResize = () => { - * if (this.inputRef.current) { - * trimLeft(inputRef.current, String(this.props.value)); - * } - * }; - * - * public render() { - * return ( - * - * ); - * } - * - * @param {Element} containerRefElement The container reference to observe - * @param {Function} handleResize The function to call for resize events - * @return {Function} The function used to unobserve resize events - */ -export const getResizeObserver = (containerRefElement: Element, handleResize: () => void) => { - let unobserve: any; - - if (canUseDOM) { - const { ResizeObserver } = window as any; - - if (containerRefElement && ResizeObserver) { - const resizeObserver = new ResizeObserver((entries: any) => { - // Wrap resize function in requestAnimationFrame to avoid "ResizeObserver loop limit exceeded" errors - window.requestAnimationFrame(() => { - if (Array.isArray(entries) && entries.length > 0) { - handleResize(); - } - }); - }); - resizeObserver.observe(containerRefElement); - unobserve = () => resizeObserver.unobserve(containerRefElement); - } else { - window.addEventListener('resize', handleResize); - unobserve = () => window.removeEventListener('resize', handleResize); - } - } - return () => { - if (unobserve) { - unobserve(); - } - }; -}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-theme.ts b/packages/react-charts/src/components/ChartUtils/chart-theme.ts deleted file mode 100644 index 6feecda5f88..00000000000 --- a/packages/react-charts/src/components/ChartUtils/chart-theme.ts +++ /dev/null @@ -1,204 +0,0 @@ -import cloneDeep from 'lodash/cloneDeep'; -import merge from 'lodash/merge'; -import { DarkBlueColorTheme } from '../ChartTheme/themes/dark/blue-color-theme'; -import { DarkCyanColorTheme } from '../ChartTheme/themes/dark/cyan-color-theme'; -import { DarkGoldColorTheme } from '../ChartTheme/themes/dark/gold-color-theme'; -import { DarkGrayColorTheme } from '../ChartTheme/themes/dark/gray-color-theme'; -import { DarkGreenColorTheme } from '../ChartTheme/themes/dark/green-color-theme'; -import { DarkMultiColorOrderedTheme } from '../ChartTheme/themes/dark/multi-color-ordered-theme'; -import { DarkMultiColorUnorderedTheme } from '../ChartTheme/themes/dark/multi-color-unordered-theme'; -import { DarkOrangeColorTheme } from '../ChartTheme/themes/dark/orange-color-theme'; -import { DarkPurpleColorTheme } from '../ChartTheme/themes/dark/purple-color-theme'; -import { LightBlueColorTheme } from '../ChartTheme/themes/light/blue-color-theme'; -import { LightCyanColorTheme } from '../ChartTheme/themes/light/cyan-color-theme'; -import { LightGoldColorTheme } from '../ChartTheme/themes/light/gold-color-theme'; -import { LightGrayColorTheme } from '../ChartTheme/themes/light/gray-color-theme'; -import { LightGreenColorTheme } from '../ChartTheme/themes/light/green-color-theme'; -import { LightMultiColorOrderedTheme } from '../ChartTheme/themes/light/multi-color-ordered-theme'; -import { LightMultiColorUnorderedTheme } from '../ChartTheme/themes/light/multi-color-unordered-theme'; -import { LightOrangeColorTheme } from '../ChartTheme/themes/light/orange-color-theme'; -import { LightPurpleColorTheme } from '../ChartTheme/themes/light/purple-color-theme'; -import { - ChartAxisTheme, - ChartBaseTheme, - ChartBulletComparativeErrorMeasureTheme, - ChartBulletComparativeMeasureTheme, - ChartBulletComparativeWarningMeasureTheme, - ChartBulletGroupTitleTheme, - ChartBulletPrimaryDotMeasureTheme, - ChartBulletPrimaryNegativeMeasureTheme, - ChartBulletPrimarySegmentedMeasureTheme, - ChartBulletTheme, - ChartBulletQualitativeRangeTheme, - ChartDonutTheme, - ChartDonutUtilizationDynamicTheme, - ChartDonutUtilizationStaticTheme, - ChartDonutThresholdDynamicTheme, - ChartDonutThresholdStaticTheme, - ChartThemeDefinition, - ChartThemeColor, - ChartThemeVariant, - ChartThresholdTheme -} from '../ChartTheme/ChartTheme'; - -// Apply custom properties to base and color themes -export const getCustomTheme = ( - themeColor: string, - themeVariant: string, - customTheme: ChartThemeDefinition -): ChartThemeDefinition => merge(getTheme(themeColor, themeVariant), customTheme); - -// Returns axis theme -export const getAxisTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartAxisTheme); - -// Returns bullet chart theme -export const getBulletTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletTheme); - -// Returns comparative error measure theme for bullet chart -export const getBulletComparativeErrorMeasureTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletComparativeErrorMeasureTheme); - -// Returns comparative measure theme for bullet chart -export const getBulletComparativeMeasureTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletComparativeMeasureTheme); - -// Returns comparative warning measure theme for bullet chart -export const getBulletComparativeWarningMeasureTheme = ( - themeColor: string, - themeVariant: string -): ChartThemeDefinition => getCustomTheme(themeColor, themeVariant, ChartBulletComparativeWarningMeasureTheme); - -// Returns group title theme for bullet chart -export const getBulletGroupTitleTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletGroupTitleTheme); - -// Returns primary dot measure theme for bullet chart -export const getBulletPrimaryDotMeasureTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletPrimaryDotMeasureTheme); - -// Returns primary negative measure theme for bullet chart -export const getBulletPrimaryNegativeMeasureTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletPrimaryNegativeMeasureTheme); - -// Returns primary segmented measure theme for bullet chart -export const getBulletPrimarySegmentedMeasureTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletPrimarySegmentedMeasureTheme); - -// Returns qualitative range theme for bullet chart -export const getBulletQualitativeRangeTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartBulletQualitativeRangeTheme); - -// Returns donut theme -export const getDonutTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartDonutTheme); - -// Returns dynamic donut threshold theme -export const getDonutThresholdDynamicTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => { - const theme = getCustomTheme(themeColor, themeVariant, ChartDonutThresholdDynamicTheme); - - // Merge just the first color of dynamic (blue, green, etc.) with static (grey) for expected colorScale - theme.legend.colorScale = [theme.pie.colorScale[0], ...ChartDonutThresholdDynamicTheme.legend.colorScale]; - - // Merge the threshold colors in case users want to show the unused data - theme.pie.colorScale = [theme.pie.colorScale[0], ...ChartDonutThresholdStaticTheme.pie.colorScale]; - return theme; -}; - -// Returns static donut threshold theme -export const getDonutThresholdStaticTheme = ( - themeColor: string, - themeVariant: string, - invert?: boolean -): ChartThemeDefinition => { - const staticTheme = cloneDeep(ChartDonutThresholdStaticTheme); - if (invert && staticTheme.pie.colorScale instanceof Array) { - staticTheme.pie.colorScale = staticTheme.pie.colorScale.reverse(); - } - return getCustomTheme(themeColor, themeVariant, staticTheme); -}; - -// Returns donut utilization theme -export const getDonutUtilizationTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => { - const theme = getCustomTheme(themeColor, themeVariant, ChartDonutUtilizationDynamicTheme); - - // Merge just the first color of dynamic (blue, green, etc.) with static (grey) for expected colorScale - theme.pie.colorScale = [theme.pie.colorScale[0], ...ChartDonutUtilizationStaticTheme.pie.colorScale]; - theme.legend.colorScale = [theme.legend.colorScale[0], ...ChartDonutUtilizationStaticTheme.legend.colorScale]; - return theme; -}; - -// Returns dark theme colors -export const getDarkThemeColors = (themeColor: string) => { - switch (themeColor) { - case ChartThemeColor.blue: - return DarkBlueColorTheme; - case ChartThemeColor.cyan: - return DarkCyanColorTheme; - case ChartThemeColor.gold: - return DarkGoldColorTheme; - case ChartThemeColor.gray: - return DarkGrayColorTheme; - case ChartThemeColor.green: - return DarkGreenColorTheme; - case ChartThemeColor.multi: - case ChartThemeColor.multiOrdered: - return DarkMultiColorOrderedTheme; - case ChartThemeColor.multiUnordered: - return DarkMultiColorUnorderedTheme; - case ChartThemeColor.orange: - return DarkOrangeColorTheme; - case ChartThemeColor.purple: - return DarkPurpleColorTheme; - default: - return DarkBlueColorTheme; - } -}; - -// Returns light theme colors -export const getLightThemeColors = (themeColor: string) => { - switch (themeColor) { - case ChartThemeColor.blue: - return LightBlueColorTheme; - case ChartThemeColor.cyan: - return LightCyanColorTheme; - case ChartThemeColor.gold: - return LightGoldColorTheme; - case ChartThemeColor.gray: - return LightGrayColorTheme; - case ChartThemeColor.green: - return LightGreenColorTheme; - case ChartThemeColor.multi: - case ChartThemeColor.multiOrdered: - return LightMultiColorOrderedTheme; - case ChartThemeColor.multiUnordered: - return LightMultiColorUnorderedTheme; - case ChartThemeColor.orange: - return LightOrangeColorTheme; - case ChartThemeColor.purple: - return LightPurpleColorTheme; - default: - return LightBlueColorTheme; - } -}; - -// Applies theme color and variant to base theme -export const getTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => { - // Deep clone - const baseTheme = { - ...JSON.parse(JSON.stringify(ChartBaseTheme)) - }; - switch (themeVariant) { - case ChartThemeVariant.dark: - return merge(baseTheme, getDarkThemeColors(themeColor)); - case ChartThemeVariant.light: - return merge(baseTheme, getLightThemeColors(themeColor)); - default: - return merge(baseTheme, getLightThemeColors(themeColor)); - } -}; - -// Returns threshold theme -export const getThresholdTheme = (themeColor: string, themeVariant: string): ChartThemeDefinition => - getCustomTheme(themeColor, themeVariant, ChartThresholdTheme); diff --git a/packages/react-charts/src/components/ChartUtils/chart-tooltip.ts b/packages/react-charts/src/components/ChartUtils/chart-tooltip.ts deleted file mode 100644 index 459c936c283..00000000000 --- a/packages/react-charts/src/components/ChartUtils/chart-tooltip.ts +++ /dev/null @@ -1,266 +0,0 @@ -/* eslint-disable camelcase */ -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; -import { Helpers, OrientationTypes, StringOrNumberOrCallback } from 'victory-core'; -import { ChartLegendProps } from '../ChartLegend'; -import { ChartLegendTooltipStyles, ChartThemeDefinition } from '../ChartTheme'; -import { getLegendDimensions } from './chart-legend'; - -interface ChartCursorTooltipCenterOffsetInterface { - offsetCursorDimensionX?: boolean; // Adjust the tooltip to appear to the right of the vertical cursor - offsetCursorDimensionY?: boolean; // Adjust the tooltip to appear above the horizontal cursor - theme?: ChartThemeDefinition; -} - -interface ChartCursorTooltipPoniterOrientationInterface { - horizontal?: boolean; - theme?: ChartThemeDefinition; -} - -interface ChartLegendTooltipFlyoutInterface { - legendData: any; - legendOrientation?: 'horizontal' | 'vertical'; - legendProps?: any; - text?: StringOrNumberOrCallback | string[] | number[]; - theme: ChartThemeDefinition; -} - -interface ChartLegendTooltipVisibleDataInterface { - activePoints?: any[]; - colorScale?: string[]; - legendData: any; - text?: StringOrNumberOrCallback | string[] | number[]; - textAsLegendData?: boolean; - theme: ChartThemeDefinition; -} - -interface ChartLegendTooltipVisibleTextInterface { - activePoints?: any[]; - legendData: any; - text: StringOrNumberOrCallback | string[] | number[]; -} - -/** - * When using a cursor container, the tooltip can be offset from the cursor point. If offsetCursorDimensionX is true, - * the tooltip will appear to the right the vertical cursor. If offsetCursorDimensionY is true, the tooltip will appear - * above the vertical cursor. - */ -export const getCursorTooltipCenterOffset = ({ - offsetCursorDimensionX = false, - offsetCursorDimensionY = false, - theme -}: ChartCursorTooltipCenterOffsetInterface) => { - const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength) : 10; - const offsetX = ({ center, flyoutWidth, width }: any) => { - const offset = flyoutWidth / 2 + pointerLength; - return width > center.x + flyoutWidth + pointerLength ? offset : -offset; - }; - const offsetY = ({ center, flyoutHeight, width }: any) => { - const offset = flyoutHeight / 2 + pointerLength; - return width > center.y + flyoutHeight + pointerLength ? -offset : offset; - }; - return { - x: offsetCursorDimensionX ? offsetX : 0, - y: offsetCursorDimensionY ? offsetY : 0 - }; -}; - -/** - * When using a cursor container, the tooltip pointer orientation can be adjusted as the cursor approaches the edge of - * the chart. If horizontal is true, the tooltip pointer will either be 'left' or 'right'. If horizontal is true, the - * tooltip pointer will either be 'top' or 'bottom'. - */ -export const getCursorTooltipPoniterOrientation = ({ - horizontal = true, - theme -}: ChartCursorTooltipPoniterOrientationInterface): ((props: any) => OrientationTypes) => { - const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength) : 10; - const orientationX = ({ center, flyoutWidth, width }: any): OrientationTypes => - width > center.x + flyoutWidth + pointerLength ? 'left' : 'right'; - const orientationY = ({ center, flyoutHeight, height }: any): OrientationTypes => - height > center.y + flyoutHeight + pointerLength ? 'top' : 'bottom'; - return horizontal ? orientationX : orientationY; -}; - -// Returns props associated with legend data -export const getLegendTooltipDataProps = (defaultProps: ChartLegendProps) => ({ - borderPadding: 0, - gutter: 0, - orientation: 'vertical', - padding: 0, - rowGutter: 0, - style: { - labels: { - fill: ChartLegendTooltipStyles.label.fill, - lineHeight: 0.275, - padding: 0 - }, - title: { - fill: ChartLegendTooltipStyles.label.fill, - padding: 0 - } - }, - ...defaultProps -}); - -// Returns the legend height and width -export const getLegendTooltipSize = ({ - legendData, - legendOrientation = 'vertical', - legendProps, - text = '', - theme -}: ChartLegendTooltipFlyoutInterface) => { - const textEvaluated = Helpers.evaluateProp(text); - const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; - - // Find max char lengths - let maxDataLength = 0; - let maxTextLength = 0; - _text.map((name: string, index: number) => { - if (name) { - if (name.length > maxTextLength) { - maxTextLength = name.length; - } - const hasData = legendData && legendData[index] && legendData[index].name; - if (hasData) { - if (legendData[index].name.length > maxDataLength) { - maxDataLength = legendData[index].name.length; - } - } - } - }); - - // Set length to ensure minimum spacing between label and value - let maxLength = maxDataLength + maxTextLength; - if (maxDataLength < 20) { - maxLength += 2; - } - - // Get spacing to help align legend labels and text values - const spacer = 'x'; - const getSpacing = (legendLabel: string, textLabel: string) => { - let spacing = ''; - if (maxLength === 0) { - return spacing; - } - const legendLabelChars = legendLabel ? legendLabel.length : 0; - const textLabelChars = textLabel ? textLabel.length : 0; - const maxChars = legendLabelChars + textLabelChars; - - // Add spacer - while (spacing.length < maxLength - maxChars) { - spacing += spacer; - } - return spacing; - }; - - // Format all text (similar to below) to help determine overall width. - // - // {name: "Cats no data"} - // {name: "Dogs 1"} - // {name: "Birds 4"} - // {name: "Mice 3"} - const data = _text.map((label: string, index: number) => { - const hasData = legendData && legendData[index] && legendData[index].name; - const spacing = hasData ? getSpacing(legendData[index].name, label) : ''; - - return { - name: `${hasData ? legendData[index].name : ''}${spacing}${label}` - }; - }); - - // Replace whitespace with spacer char for consistency in width - const formattedData = data.map(val => ({ - name: val.name.replace(/ /g, spacer) - })); - - // This should include both legend data and text - const widthDimensions = getLegendDimensions({ - legendData: formattedData, - legendOrientation, - legendProps, - theme - }); - // This should only use text. The row gutter changes when displaying all "no data" messages - const heightDimensions = getLegendDimensions({ - legendData: _text.map((name: string) => ({ name })), - legendOrientation, - legendProps, - theme - }); - return { - height: heightDimensions.height, - width: widthDimensions.width > 0 ? widthDimensions.width : 0 - }; -}; - -// Returns visible legend data, while syncing color scale. If textAsLegendData is true, the text prop is used as -// legend data so y values can be passed individually to the label component -export const getLegendTooltipVisibleData = ({ - activePoints, - colorScale, - legendData, - text, - textAsLegendData = false, - theme -}: ChartLegendTooltipVisibleDataInterface) => { - const textEvaluated = Helpers.evaluateProp(text); - const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; - const result = []; - - // Sync data with interactive legends - if (legendData) { - let index = -1; - for (let i = 0; i < legendData.length; i++) { - const data = legendData[i]; - const activePoint = activePoints ? activePoints.find(item => item.childName === data.childName) : ''; - if ( - !activePoint || - (data.symbol && data.symbol.type === 'eyeSlash' && data.symbol.fill === chart_color_black_500.value) - ) { - continue; // Skip hidden data - } - if (index++ < _text.length - 1) { - const themeColor = - theme && theme.legend && theme.legend.colorScale - ? theme.legend.colorScale[i % theme.legend.colorScale.length] - : undefined; - result.push({ - name: textAsLegendData ? _text[index] : data.name, - symbol: { - fill: colorScale ? colorScale[i % colorScale.length] : themeColor, // Sync color scale - ...data.symbol - } - }); - } - } - } - return result; -}; - -// Returns visible text for interactive legends -export const getLegendTooltipVisibleText = ({ - activePoints, - legendData, - text -}: ChartLegendTooltipVisibleTextInterface) => { - const textEvaluated = Helpers.evaluateProp(text); - const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; - const result = []; - if (legendData) { - let index = -1; - for (const data of legendData) { - const activePoint = activePoints ? activePoints.find(item => item.childName === data.childName) : ''; - if ( - !activePoint || - (data.symbol && data.symbol.type === 'eyeSlash' && data.symbol.fill === chart_color_black_500.value) - ) { - continue; // Skip hidden data - } - if (index++ < _text.length - 1) { - result.push(_text[index]); - } - } - } - return result; -}; diff --git a/packages/react-charts/src/components/ChartUtils/index.ts b/packages/react-charts/src/components/ChartUtils/index.ts deleted file mode 100644 index 500274f357f..00000000000 --- a/packages/react-charts/src/components/ChartUtils/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export * from './chart-container'; -export * from './chart-domain'; -export * from './chart-helpers'; -export * from './chart-interactive-legend'; -export * from './chart-label'; -export * from './chart-legend'; -export * from './chart-origin'; -export * from './chart-padding'; -export * from './chart-resize'; -export * from './chart-theme'; -export * from './chart-tooltip'; diff --git a/packages/react-charts/src/components/ChartVoronoiContainer/ChartVoronoContainer.test.tsx b/packages/react-charts/src/components/ChartVoronoiContainer/ChartVoronoContainer.test.tsx deleted file mode 100644 index db72f327abc..00000000000 --- a/packages/react-charts/src/components/ChartVoronoiContainer/ChartVoronoContainer.test.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ChartArea } from '../ChartArea'; -import { ChartGroup } from '../ChartGroup'; -import { ChartVoronoiContainer } from './ChartVoronoiContainer'; - -Object.values([true, false]).forEach(() => { - test('ChartVoronoiContainer', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); -}); - -test('renders container via ChartGroup', () => { - const view = shallow( - } height={200} width={200}> - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-charts/src/components/ChartVoronoiContainer/__snapshots__/ChartVoronoContainer.test.tsx.snap b/packages/react-charts/src/components/ChartVoronoiContainer/__snapshots__/ChartVoronoContainer.test.tsx.snap deleted file mode 100644 index e68121f1435..00000000000 --- a/packages/react-charts/src/components/ChartVoronoiContainer/__snapshots__/ChartVoronoContainer.test.tsx.snap +++ /dev/null @@ -1,2879 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ChartVoronoiContainer 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - renderInPortal={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - /> - } - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - voronoiPadding={5} -/> -`; - -exports[`ChartVoronoiContainer 2`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - renderInPortal={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - /> - } - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - voronoiPadding={5} -/> -`; - -exports[`renders container via ChartGroup 1`] = ` -} - role="presentation" - shapeRendering="auto" - /> - } - groupComponent={} - labelComponent={ - } - capHeight={0.71} - direction="inherit" - groupComponent={} - lineHeight={1} - textComponent={} - tspanComponent={} - /> - } - renderInPortal={true} - /> - } - portalComponent={} - portalZIndex={99} - responsive={true} - role="img" - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - voronoiPadding={5} - /> - } - groupComponent={} - height={200} - samples={50} - sortOrder="ascending" - standalone={true} - theme={ - Object { - "area": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "fillOpacity": 0.3, - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "axis": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "axis": Object { - "fill": "transparent", - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - "axisLabel": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 40, - "stroke": "transparent", - "textAnchor": "middle", - }, - "grid": Object { - "fill": "none", - "pointerEvents": "painted", - "stroke": "none", - "strokeLinecap": "round", - "strokeLinejoin": "round", - }, - "tickLabels": Object { - "fill": "#4f5255", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "ticks": Object { - "fill": "transparent", - "size": 5, - "stroke": "#d2d2d2", - "strokeLinecap": "round", - "strokeLinejoin": "round", - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "bar": Object { - "barWidth": 10, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#06c", - "padding": 8, - "stroke": "none", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "boxplot": Object { - "boxWidth": 20, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "max": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "maxLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "median": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "medianLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "min": Object { - "padding": 8, - "stroke": "#151515", - "strokeWidth": 1, - }, - "minLabels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q1": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q1Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "q3": Object { - "fill": "#8a8d90", - "padding": 8, - }, - "q3Labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - }, - "width": 450, - }, - "candlestick": Object { - "candleColors": Object { - "negative": "#151515", - "positive": "#fff", - }, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "chart": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "errorbar": Object { - "borderWidth": 8, - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#151515", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "group": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "width": 450, - }, - "legend": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "gutter": 20, - "orientation": "horizontal", - "style": Object { - "data": Object { - "type": "square", - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - }, - "title": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 2, - "stroke": "transparent", - }, - }, - "titleOrientation": "top", - }, - "line": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "opacity": 1, - "stroke": "#06c", - "strokeWidth": 2, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "pie": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 230, - "padding": 20, - "style": Object { - "data": Object { - "padding": 8, - "stroke": "transparent", - "strokeWidth": 1, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "stroke": "transparent", - }, - }, - "width": 230, - }, - "scatter": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "#151515", - "opacity": 1, - "stroke": "transparent", - "strokeWidth": 0, - }, - "labels": Object { - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 10, - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - "stack": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "strokeWidth": 1, - }, - }, - "width": 450, - }, - "tooltip": Object { - "cornerRadius": 0, - "flyoutPadding": 8, - "flyoutStyle": Object { - "cornerRadius": 0, - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 0, - }, - "pointerLength": 10, - "pointerWidth": 20, - "style": Object { - "fill": "#f0f0f0", - "pointerEvents": "none", - }, - }, - "voronoi": Object { - "colorScale": Array [ - "#06c", - "#8bc1f7", - "#002f5d", - "#519de9", - "#004b95", - ], - "height": 300, - "padding": 50, - "style": Object { - "data": Object { - "fill": "transparent", - "stroke": "transparent", - "strokeWidth": 0, - }, - "flyout": Object { - "fill": "#151515", - "pointerEvents": "none", - "stroke": "#151515", - "strokeWidth": 1, - }, - "labels": Object { - "fill": "#f0f0f0", - "fontFamily": "\\"RedHatText\\",\\"Overpass\\",overpass,helvetica,arial,sans-serif", - "fontSize": 14, - "letterSpacing": "normal", - "padding": 8, - "pointerEvents": "none", - "stroke": "transparent", - "textAnchor": "middle", - }, - }, - "width": 450, - }, - } - } - width={200} -> - - - -`; diff --git a/packages/react-charts/src/components/ChartVoronoiContainer/index.ts b/packages/react-charts/src/components/ChartVoronoiContainer/index.ts deleted file mode 100644 index 12edda1b315..00000000000 --- a/packages/react-charts/src/components/ChartVoronoiContainer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartVoronoiContainer'; diff --git a/packages/react-charts/src/components/Sparkline/examples/sparkline.md b/packages/react-charts/src/components/Sparkline/examples/sparkline.md deleted file mode 100644 index d28d288335e..00000000000 --- a/packages/react-charts/src/components/Sparkline/examples/sparkline.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -id: Sparkline chart -section: charts -propComponents: [ - 'ChartArea', - 'ChartContainer', - 'ChartGroup', - 'ChartLabel', - 'ChartVoronoiContainer' -] -hideDarkMode: true ---- - -import { ChartArea, ChartContainer, ChartGroup, ChartLabel, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; -import './sparkline.css'; - -## Introduction -Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! - -PatternFly React charts are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. - -Learn to build a sparkline chart using a Katacoda tutorial starting with a simple chart, adding tooltips, and concluding by changing the theme color. You'll learn how to use React chart components together to build a consistent user experience. - -[Start course](https://katacoda.com/patternfly/courses/react-charts/sparkline-chart) - -## Examples -### Basic -```js -import React from 'react'; -import { ChartArea, ChartContainer, ChartGroup, ChartLabel, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    -
    - `${datum.name}: ${datum.y}`} constrainToVisibleArea />} - height={100} - maxDomain={{y: 9}} - padding={0} - width={400} - > - - -
    - - - -
    -``` - -### Green - -This demonstrates an alternate way of applying tooltips using CSS overflow - -```js -import React from 'react'; -import { ChartArea, ChartContainer, ChartGroup, ChartLabel, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts'; - -
    -
    - `${datum.name}: ${datum.y}`} />} - height={100} - maxDomain={{y: 9}} - padding={0} - themeColor={ChartThemeColor.green} - width={400} - > - - -
    - - - -
    -``` - -## Documentation -### Tips -- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) -- For single data points or zero values, you may want to set the `domain` prop -- Use `ChartGroup` in place of `Chart` when an axis and labels are not desired -- Themes are inherited, so a default theme may override `themeColor` for a child component -- The `theme` and `themeColor` props should be applied at the most top level component - -### Note -Currently, the generated documention below is not able to resolve type definitions from Victory imports. For the -components used in the examples above, Victory pass-thru props are also documented here: - - - For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) - - For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) - - For `ChartLabel` props, see [VictoryLabel](https://formidable.com/open-source/victory/docs/victory-label) - - For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/components/index.ts b/packages/react-charts/src/components/index.ts deleted file mode 100644 index ef12f1079ef..00000000000 --- a/packages/react-charts/src/components/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** Keep alphabetically sorted */ -export * from './Chart'; -export * from './ChartArea'; -export * from './ChartAxis'; -export * from './ChartBar'; -export * from './ChartBullet'; -export * from './ChartContainer'; -export * from './ChartCursorContainer'; -export * from './ChartCursorTooltip'; -export * from './ChartDonut'; -export * from './ChartDonutUtilization'; -export * from './ChartGroup'; -export * from './ChartLabel'; -export * from './ChartLegend'; -export * from './ChartLegendTooltip'; -export * from './ChartLine'; -export * from './ChartPie'; -export * from './ChartPoint'; -export * from './ChartScatter'; -export * from './ChartStack'; -export * from './ChartTheme'; -export * from './ChartThreshold'; -export * from './ChartTooltip'; -export * from './ChartUtils'; -export * from './ChartVoronoiContainer'; diff --git a/packages/react-charts/src/echarts/__mocks__/echarts.ts b/packages/react-charts/src/echarts/__mocks__/echarts.ts new file mode 100644 index 00000000000..52c5c5c2c22 --- /dev/null +++ b/packages/react-charts/src/echarts/__mocks__/echarts.ts @@ -0,0 +1,6 @@ +const echarts: any = jest.createMockFromModule('echarts'); +echarts.init = jest.fn(() => ({ + setOption: jest.fn(), + dispose: jest.fn() +})); +module.exports = echarts; diff --git a/packages/react-charts/src/echarts/components/Charts/Charts.tsx b/packages/react-charts/src/echarts/components/Charts/Charts.tsx new file mode 100644 index 00000000000..ae9002fd9a3 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Charts/Charts.tsx @@ -0,0 +1,252 @@ +import { FunctionComponent, useEffect } from 'react'; +import { useCallback, useReducer, useRef } from 'react'; +import cloneDeep from 'lodash/cloneDeep'; +import defaultsDeep from 'lodash/defaultsDeep'; + +import * as echarts from 'echarts/core'; +import { EChartsInitOpts } from 'echarts/types/dist/echarts'; +import { EChartsOption } from 'echarts/types/dist/option'; +import { TooltipOption } from 'echarts/types/dist/shared'; + +import { getLineSeries } from '../Line'; +import { getSankeySeries } from '../Sankey'; + +import { ThemeDefinition } from '../themes/Theme'; +import { getMutationObserver } from '../utils/observe'; +import { getClassName } from '../utils/styles'; +import { getTheme } from '../utils/theme'; +import { getLegendTooltip, getSankeyTooltip } from '../utils/tooltip'; +import { ThemeColor } from '../themes/ThemeColor'; + +/** + * See https://echarts.apache.org/en/option.html#tooltip + * + * @public + * @beta + */ +export interface TooltipOptionProps extends TooltipOption { + /** + * The destination label shown in the tooltip -- for Sankey only + */ + destinationLabel?: string; + /** + * The source label shown in the tooltip -- for Sankey only + */ + sourceLabel?: string; +} + +/** + * See https://echarts.apache.org/en/option.html + * + * @public + * @beta + */ +export interface ChartsOptionProps extends EChartsOption { + /** + * Tooltip component -- see https://echarts.apache.org/en/option.html#tooltip + */ + tooltip?: TooltipOptionProps | TooltipOptionProps[]; +} + +/** + * This component is based on the Apache ECharts chart library. It provides additional functionality, custom + * components, and theming for PatternFly. This provides a collection of React based components you can use to build + * PatternFly patterns with consistent markup, styling, and behavior. + * + * See https://echarts.apache.org/en/api.html#echarts + * + * @public + * @beta + */ +export interface ChartsProps { + /** + * The className prop specifies a class name that will be applied to outermost element + */ + className?: string; + /** + * Specify height explicitly, in pixels + */ + height?: number; + /** + * The id prop specifies an ID that will be applied to outermost element. + */ + id?: string; + /** + * Flag indicating to use the legend tooltip (default). This may be overridden by the `option.tooltip` property. + */ + isLegendTooltip?: boolean; + /** + * Flag indicating to use the SVG renderer (default). This may be overridden by the `opts.renderer` property. + */ + isSvgRenderer?: boolean; + /** + * This creates a Mutation Observer to watch the given DOM selector. + * + * When the pf-v6-theme-dark selector is added or removed, this component will be notified to update its computed + * theme styles. However, if the dark theme is not updated dynamically (e.g., via a toggle), there is no need to add + * this Mutation Observer. + * + * Note: Don't provide ".pf-v6-theme-dark" as the node selector as it won't exist in the page for light theme. + * The underlying querySelectorAll() function needs to find the element the dark theme selector will be added to. + * + * See https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Locating_DOM_elements_using_selectors + * + * @propType string + * @example + * @example + * @example + */ + nodeSelector?: string; + /** + * ECharts uses this object to configure its properties; for example, series, title, and tooltip + * + * See https://echarts.apache.org/en/option.html + */ + option?: ChartsOptionProps; + /** + * Optional chart configuration + * + * See https://echarts.apache.org/en/api.html#echarts.init + */ + opts?: EChartsInitOpts; + /** + * The theme prop specifies a theme to use for determining styles and layout properties for a component. Any styles or + * props defined in theme may be overwritten by props specified on the component instance. + * + * See https://echarts.apache.org/handbook/en/concepts/style/#theme + */ + theme?: ThemeDefinition; + /** + * Specifies the theme color. Valid values are 'blue', 'green', 'multi', etc. + * + * Note: Not compatible with theme prop + * + * @example themeColor={ChartThemeColor.blue} + */ + themeColor?: string; + /** + * Specify width explicitly, in pixels + */ + width?: number; +} +export const Charts: FunctionComponent = ({ + className, + height, + id, + isLegendTooltip = true, + isSvgRenderer = true, + nodeSelector, + option, + opts, + theme, + themeColor, + width, + ...rest +}: ChartsProps) => { + const containerRef = useRef(null); + const echart = useRef(null); + const [update, forceUpdate] = useReducer((x) => x + 1, 0); + + const getSize = () => ({ + ...(height && { height: `${height}px` }), + ...(width && { width: `${width}px` }) + }); + + const getTooltip = useCallback( + (series: any[], tooltipType: string, isSkeleton: boolean, echart) => { + // Skeleton should not have any interactions + if (isSkeleton) { + return undefined; + } else if (tooltipType === 'sankey') { + return getSankeyTooltip(series, option); + } else if (tooltipType === 'legend') { + return getLegendTooltip(series, option, echart); + } + return option.tooltip; + }, + [option] + ); + + const getSeries = useCallback( + (chartTheme: ThemeDefinition, isSkeleton: boolean) => { + let tooltipType; + const series: any = cloneDeep(option?.series); + const newSeries = []; + + series.map((serie: any) => { + switch (serie.type) { + case 'sankey': + tooltipType = 'sankey'; // Overrides legend tooltip + newSeries.push(getSankeySeries(serie, chartTheme, isSkeleton)); + break; + case 'line': + if (!tooltipType) { + tooltipType = 'legend'; + } + newSeries.push(getLineSeries(serie, chartTheme, isSkeleton)); + break; + default: + newSeries.push(serie); + break; + } + }); + return { series, tooltipType }; + }, + [option?.series] + ); + + useEffect(() => { + const isSkeleton = themeColor === ThemeColor.skeleton; + const chartTheme = theme ? theme : getTheme(themeColor); + const renderer = isSvgRenderer ? 'svg' : 'canvas'; + + echart.current = echarts.init( + containerRef.current, + chartTheme, + defaultsDeep(opts, { height, renderer, width }) // height and width are necessary here for unit tests + ); + + const { series, tooltipType } = getSeries(chartTheme, isSkeleton); + echart.current?.setOption({ + ...option, + ...(isLegendTooltip && { tooltip: getTooltip(series, tooltipType, isSkeleton, echart.current) }), + series + }); + + return () => { + echart.current?.dispose(); + }; + }, [ + containerRef, + getSeries, + getTooltip, + height, + isLegendTooltip, + isSvgRenderer, + option, + opts, + theme, + themeColor, + update, + width + ]); + + // Resize observer + useEffect(() => { + echart.current?.resize(); + }, [height, width]); + + // Dark theme observer + useEffect(() => { + let observer = () => {}; + observer = getMutationObserver(nodeSelector, () => { + forceUpdate(); + }); + return () => { + observer(); + }; + }, [nodeSelector]); + + return
    ; +}; +Charts.displayName = 'Charts'; diff --git a/packages/react-charts/src/echarts/components/Charts/docs/Charts.tsx b/packages/react-charts/src/echarts/components/Charts/docs/Charts.tsx new file mode 100644 index 00000000000..dbd01f55105 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Charts/docs/Charts.tsx @@ -0,0 +1,411 @@ +import { EChartsInitOpts } from 'echarts/types/dist/echarts'; +import { EChartsOption } from 'echarts/types/dist/option'; +import { + AngleAxisOption, + AriaOption, + AxisPointerOption, + BrushOption, + CalendarOption, + DatasetOption, + DataZoomComponentOption, + GeoOption, + GraphicComponentLooseOption, + GridOption, + LegendComponentOption, + ParallelCoordinateSystemOption, + PolarOption, + RadarOption, + RadiusAxisOption, + SingleAxisOption, + TimelineOption, + TitleOption, + ToolboxComponentOption, + VisualMapComponentOption, + XAXisOption, + YAXisOption +} from 'echarts/types/dist/shared'; + +// The properties below exist to document properties in the example docs. Some EChart types are not exported and too +// complex to recreate here. Attempting to duplicate each EChart type would be error-prone. For documentation purposes, +// we shall define simple types here, which avoids having to duplicate EChart's complex object types. + +/** + * See https://echarts.apache.org/en/option.html#tooltip + * + * @private Not intended as public API and subject to change + */ +export interface TooltipOptionProps { + /** + * Whether to show tooltip content all the time -- see https://echarts.apache.org/en/option.html#tooltip.alwaysShowContent + */ + alwaysShowContent?: boolean; + /** + * Which DOM element to append the tooltip to -- see https://echarts.apache.org/en/option.html#tooltip.appendTo + */ + appendTo?: string | HTMLElement | Function; + /** + * Configuration item for axisPointer -- see https://echarts.apache.org/en/option.html#tooltip.axisPointer + */ + axisPointer?: Object; + /** + * The background color of tooltip's floating layer -- see https://echarts.apache.org/en/option.html#tooltip.backgroundColor + */ + backgroundColor?: string; + /** + * The border color of tooltip's floating layer -- see https://echarts.apache.org/en/option.html#tooltip.borderColor + */ + borderColor?: string; + /** + * The border width of tooltip's floating layer -- see https://echarts.apache.org/en/option.html#tooltip.borderWidth + */ + borderWidth?: number; + /** + * Specify the classes for the tooltip root DOM -- see https://echarts.apache.org/en/option.html#tooltip.className + */ + className?: string; + /** + * Whether confine tooltip content in the view rect of chart instance -- see https://echarts.apache.org/en/option.html#tooltip.confine + */ + confine?: boolean; + /** + * The destination label shown in the tooltip -- for Sankey only + */ + destinationLabel?: string; + /** + * Whether mouse is allowed to enter the floating layer of tooltip -- see https://echarts.apache.org/en/option.html#tooltip.enterable + */ + enterable?: boolean; + /** + * Extra CSS style for floating layer -- see https://echarts.apache.org/en/option.html#tooltip.extraCssText + */ + extraCssText?: string; + /** + * The content formatter of tooltip's floating layer -- see https://echarts.apache.org/en/option.html#tooltip.formatter + */ + formatter?: string | Function; + /** + * Delay time for hiding tooltip -- see https://echarts.apache.org/en/option.html#tooltip.hideDelay + */ + hideDelay?: number; + /** + * Tooltip order for multiple series -- see https://echarts.apache.org/en/option.html#tooltip.order + */ + order?: string; + /** + * The floating layer of tooltip space around content -- see https://echarts.apache.org/en/option.html#tooltip.padding + */ + padding?: number; + /** + * The position of the tooltip's floating layer -- see https://echarts.apache.org/en/option.html#tooltip.position + */ + position?: string[]; + /** + * Render mode for tooltip -- see https://echarts.apache.org/en/option.html#tooltip.renderMode + */ + renderMode?: string; + /** + * Whether to show the tooltip component -- see https://echarts.apache.org/en/option.html#tooltip.show + */ + show?: boolean; + /** + * Whether to show the tooltip floating layer -- see https://echarts.apache.org/en/option.html#tooltip.showContent + */ + showContent?: boolean; + /** + * Delay time for showing tooltip -- see https://echarts.apache.org/en/option.html#tooltip.showDelay + */ + showDelay?: number; + /** + * The source label shown in the tooltip -- for Sankey only + */ + sourceLabel?: string; + /** + * The text style of tooltip's floating layer -- see https://echarts.apache.org/en/option.html#tooltip.textStyle + */ + textStyle?: Object; + /** + * The transition duration of tooltip's animation, in seconds -- see https://echarts.apache.org/en/option.html#tooltip.transitionDuration + */ + transitionDuration?: number; + /** + * Type of triggering -- see https://echarts.apache.org/en/option.html#tooltip.trigger + */ + trigger?: string; + /** + * Conditions to trigger tooltip -- see https://echarts.apache.org/en/option.html#tooltip.triggerOn + */ + triggerOn?: 'mousemove' | 'click' | 'mousemove|click' | 'none'; + /** + * Callback function for formatting the value section in tooltip -- see https://echarts.apache.org/en/option.html#tooltip.valueFormatter + */ + valueFormatter?: string; +} + +/** + * See https://echarts.apache.org/en/option.html + * + * @private Not intended as public API and subject to change + */ +export interface ChartsOptionProps { + /** + * The angle axis in Polar Coordinate -- see https://echarts.apache.org/en/option.html#angleAxis + */ + angleAxis?: AngleAxisOption | AngleAxisOption[]; + /** + * Whether to enable animation -- see https://echarts.apache.org/en/option.html#animation + */ + animation?: boolean; + /** + * Delay before updating the first animation -- see https://echarts.apache.org/en/option.html#animationDelay + */ + animationDelay?: number; + /** + * Delay before updating animation -- see https://echarts.apache.org/en/option.html#animationDelayUpdate + */ + animationDelayUpdate?: number; + /** + * Duration of the first animation -- see https://echarts.apache.org/en/option.html#animationDuration + */ + animationDuration?: number; + /** + * Time for animation to complete -- see https://echarts.apache.org/en/option.html#animationDurationUpdate + */ + animationDurationUpdate?: number; + /** + * Easing method used for the first animation -- see https://echarts.apache.org/en/option.html#animationEasing + */ + animationEasing?: string; + /** + * Easing method used for animation -- see https://echarts.apache.org/en/option.html#animationEasingUpdate + */ + animationEasingUpdate?: string; + /** + * Whether to set graphic number threshold to animation -- see https://echarts.apache.org/en/option.html#animationThreshold + */ + animationThreshold?: number; + /** + * The W3C has developed the WAI-ARIA, the Accessible Rich Internet Applications Suite, which is dedicated to making web content and web applications accessible -- see https://echarts.apache.org/en/option.html#aria + */ + aria?: AriaOption; + /** + * This is the global configurations of axisPointer -- see https://echarts.apache.org/en/option.html#axisPointer + */ + axisPointer?: AxisPointerOption | AxisPointerOption[]; + /** + * Background color - see https://echarts.apache.org/en/option.html#backgroundColor + */ + backgroundColor?: string; + /** + * Sets the type of compositing operation to apply when drawing a new shape -- see https://echarts.apache.org/en/option.html#blendMode + */ + blendMode?: string; + /** + * Brush is an area-selecting component -- see https://echarts.apache.org/en/option.html#brush + */ + brush?: BrushOption | BrushOption[]; + /** + * Calendar coordinates -- see https://echarts.apache.org/en/option.html#calendar + */ + calendar?: CalendarOption | CalendarOption[]; + /** + * The color list of palette -- see https://echarts.apache.org/en/option.html#color + */ + color?: string[]; + /** + * Dataset brings convenience in data management separated with styles and enables data reuse by different series -- see https://echarts.apache.org/en/option.html#dataset + */ + dataset?: DatasetOption | DatasetOption[]; + /** + * Data zoom component is used for zooming a specific area -- see https://echarts.apache.org/en/option.html#dataZoom + */ + dataZoom?: DataZoomComponentOption | DataZoomComponentOption[]; + /** + * ECharts will automatically detect it via backgroundColor by default and adjust the text color accordingly - see https://echarts.apache.org/en/option.html#darkMode + */ + darkMode?: boolean | 'auto'; + /** + * ECharts will automatically detect it via backgroundColor by default and adjust the text color accordingly -- see https://echarts.apache.org/en/option.html#darkMode + */ + /** + * Geographic coordinate system component -- see https://echarts.apache.org/en/option.html#geo + */ + geo?: GeoOption | GeoOption[]; + /** + * Graphic component enables creating graphic elements in ECharts -- see https://echarts.apache.org/en/option.html#graphic + */ + graphic?: GraphicComponentLooseOption | GraphicComponentLooseOption[]; + /** + * Drawing grid in rectangular coordinate -- see https://echarts.apache.org/en/option.html#grid + */ + grid?: GridOption | GridOption[]; + /** + * When the number of element of the whole chart is larger than hoverLayerThreshold, a separate hover layer is used to render hovered elements -- see https://echarts.apache.org/en/option.html#hoverLayerThreshold + */ + hoverLayerThreshold?: number; + /** + * Legend component -- see https://echarts.apache.org/en/option.html#legend + */ + legend?: LegendComponentOption | LegendComponentOption[]; + /** + * See Responsive Mobile-End for details -- see https://echarts.apache.org/en/option.html#media + */ + media?: Object; + /** + * Option array used in timeline -- see https://echarts.apache.org/en/option.html#options + */ + options?: EChartsOption[]; + /** + * Parallel Coordinates is a common way of visualizing high-dimensional geometry and analyzing multivariate data -- see https://echarts.apache.org/en/option.html#parallel + */ + parallel?: ParallelCoordinateSystemOption | ParallelCoordinateSystemOption[]; + /** + * This component is the coordinate axis for parallel coordinate -- see https://echarts.apache.org/en/option.html#parallelAxis + * + * @type ParallelAxisOption | ParallelAxisOption[] + */ + parallelAxis?: Object; + /** + * Polar coordinate can be used in scatter and line chart -- see https://echarts.apache.org/en/option.html#polar + */ + polar?: PolarOption | PolarOption[]; + /** + * Coordinate for radar charts -- see https://echarts.apache.org/en/option.html#radar + */ + radar?: RadarOption | RadarOption[]; + /** + * Radial axis of polar coordinate -- see https://echarts.apache.org/en/option.html#radiusAxis + */ + radiusAxis?: RadiusAxisOption | RadiusAxisOption[]; + /** + * Properties for various chart types -- see https://echarts.apache.org/en/option.html#series + * + * @type SeriesOption | SeriesOption[] + */ + series?: Object; + /** + * An axis with a single dimension -- see https://echarts.apache.org/en/option.html#singleAxis + */ + singleAxis?: SingleAxisOption | SingleAxisOption[]; + /** + * Animation configurations of state switchment -- see https://echarts.apache.org/en/option.html#stateAnimation + */ + stateAnimation?: Object; + /** + * Timeline component -- see https://echarts.apache.org/en/option.html#timeline + * + * @type TimelineOption | SliderTimelineOption + */ + timeline?: TimelineOption | Object; + /** + * Title component, including main title and subtitle -- see https://echarts.apache.org/en/option.html#title + */ + title?: TitleOption | TitleOption[]; + /** + * A group of utility tools -- see https://echarts.apache.org/en/option.html#toolbox + */ + toolbox?: ToolboxComponentOption | ToolboxComponentOption[]; + /** + * Tooltip component -- see https://echarts.apache.org/en/option.html#tooltip + */ + tooltip?: TooltipOptionProps | TooltipOptionProps[]; + /** + * Whether to use UTC in display -- see https://echarts.apache.org/en/option.html#useUTC + */ + useUTC?: boolean; + /** + * Visual map is a type of component for visual encoding -- see https://echarts.apache.org/en/option.html#visualMap + */ + visualMap?: VisualMapComponentOption | VisualMapComponentOption[]; + /** + * The x-axis in cartesian(rectangular) coordinate -- see https://echarts.apache.org/en/option.html#xAxis + */ + xAxis?: XAXisOption | XAXisOption[]; + /** + * The y-axis in cartesian(rectangular) coordinate -- see https://echarts.apache.org/en/option.html#yAxis + */ + yAxis?: YAXisOption | YAXisOption[]; +} + +/** + * This component is based on the Apache ECharts chart library. It provides additional functionality, custom + * components, and theming for PatternFly. This provides a collection of React based components you can use to build + * PatternFly patterns with consistent markup, styling, and behavior. + * + * See https://echarts.apache.org/en/api.html#echarts + * + * @private Not intended as public API and subject to change + * @beta + */ +export interface Charts { + /** + * The className prop specifies a class name that will be applied to outermost element + */ + className?: string; + /** + * Specify height explicitly, in pixels + */ + height?: number; + /** + * The id prop specifies an ID that will be applied to outermost element. + */ + id?: string; + /** + * Flag indicating to use the legend tooltip (default). This may be overridden by the `option.tooltip` property. + */ + isLegendTooltip?: boolean; + /** + * Flag indicating to use the SVG renderer (default). This may be overridden by the `opts.renderer` property. + */ + isSvgRenderer?: boolean; + /** + * This creates a Mutation Observer to watch the given DOM selector. + * + * When the pf-v6-theme-dark selector is added or removed, this component will be notified to update its computed + * theme styles. However, if the dark theme is not updated dynamically (e.g., via a toggle), there is no need to add + * this Mutation Observer. + * + * Note: Don't provide ".pf-v6-theme-dark" as the node selector as it won't exist in the page for light theme. + * The underlying querySelectorAll() function needs to find the element the dark theme selector will be added to. + * + * See https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Locating_DOM_elements_using_selectors + * + * @propType string + * @example + * @example + * @example + */ + nodeSelector?: string; + /** + * ECharts uses this object to configure its properties; for example, series, title, and tooltip + * + * See https://echarts.apache.org/en/option.html + */ + option?: ChartsOptionProps; + /** + * Optional chart configuration + * + * See https://echarts.apache.org/en/api.html#echarts.init + */ + opts?: EChartsInitOpts; + /** + * The theme prop specifies a theme to use for determining styles and layout properties for a component. Any styles or + * props defined in theme may be overwritten by props specified on the component instance. + * + * See https://echarts.apache.org/handbook/en/concepts/style/#theme + * + * @type ThemeDefinition + */ + theme?: any; + /** + * Specifies the theme color. Valid values are 'blue', 'green', 'multi', etc. + * + * Note: Not compatible with theme prop + * + * @example themeColor={ChartThemeColor.blue} + */ + themeColor?: string; + /** + * Specify width explicitly, in pixels + */ + width?: number; +} diff --git a/packages/react-charts/src/echarts/components/Charts/index.ts b/packages/react-charts/src/echarts/components/Charts/index.ts new file mode 100644 index 00000000000..36eda29c1da --- /dev/null +++ b/packages/react-charts/src/echarts/components/Charts/index.ts @@ -0,0 +1 @@ +export * from './Charts'; diff --git a/packages/react-charts/src/echarts/components/Line/Line.tsx b/packages/react-charts/src/echarts/components/Line/Line.tsx new file mode 100644 index 00000000000..8010ed87caf --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/Line.tsx @@ -0,0 +1,22 @@ +import defaultsDeep from 'lodash/defaultsDeep'; + +import { ThemeDefinition } from '../themes/Theme'; + +/** + * Returns series properties for Line chart + * + * @param serie + * @param theme + * @param isSkeleton + * @private Not intended as public API and subject to change + */ +export const getLineSeries = (serie: any, theme: ThemeDefinition, isSkeleton: boolean) => { + const defaults = { + emphasis: { + ...(isSkeleton ? { disabled: true } : { focus: 'adjacency' }) + }, + showSymbol: false, + type: 'line' + }; + return defaultsDeep(serie, defaults); +}; diff --git a/packages/react-charts/src/echarts/components/Line/__tests__/Line.test.tsx b/packages/react-charts/src/echarts/components/Line/__tests__/Line.test.tsx new file mode 100644 index 00000000000..a089e491d09 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/__tests__/Line.test.tsx @@ -0,0 +1,90 @@ +import { setupJestCanvasMock } from 'jest-canvas-mock'; +import { render, screen } from '@testing-library/react'; +import { Charts } from '../../Charts'; + +import * as echarts from 'echarts/core'; +import { LineChart } from 'echarts/charts'; +import { GridComponent, TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([GridComponent, LineChart, SVGRenderer, TitleComponent, TooltipComponent]); + +beforeEach(() => { + jest.resetAllMocks(); + jest.mock('echarts'); + setupJestCanvasMock(); +}); + +const props: any = { + height: 400, + id: 'line-chart', + option: { + xAxis: { + type: 'category', + data: ['2015', '2016', '2017', '2018'] + }, + yAxis: { + axisLabel: { + formatter: (value) => (value !== 0 ? `${value}` : '') + }, + splitNumber: 3, + type: 'value' + }, + series: [ + { + data: [1, 2, 5, 3], + name: 'Cats', + type: 'line' + }, + { + data: [2, 1, 7, 4], + name: 'Dogs', + lineStyle: { + type: 'dashed' + }, + type: 'line' + }, + { + data: [3, 4, 9, 5], + name: 'Birds', + type: 'line' + }, + { + data: [3, 3, 8, 7], + name: 'Mice', + type: 'line' + } + ], + title: { + text: 'This is a Line chart' + } + }, + width: 800 +}; + +// Remove dynamic _echarts_instance_ ID +const removeInstanceID = (fragment) => { + fragment.getElementById('line-chart').removeAttribute('_echarts_instance_'); + return fragment; +}; + +test('renders component', () => { + const { asFragment } = render(); + expect(removeInstanceID(asFragment())).toMatchSnapshot(); +}); + +test('renders title', async () => { + render(); + + const title = await screen.findByText(props.option.title.text); + expect(title).toMatchSnapshot(); +}); + +test('renders height and width', async () => { + const { asFragment } = render(); + + const svg = asFragment().querySelector('svg'); + expect(svg).toHaveAttribute('height', `${props.height}`); + expect(svg).toHaveAttribute('width', `${props.width}`); +}); diff --git a/packages/react-charts/src/echarts/components/Line/__tests__/__snapshots__/Line.test.tsx.snap b/packages/react-charts/src/echarts/components/Line/__tests__/__snapshots__/Line.test.tsx.snap new file mode 100644 index 00000000000..336a0e0cd73 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/__tests__/__snapshots__/Line.test.tsx.snap @@ -0,0 +1,268 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders component 1`] = ` + +
    +
    + + + + + + + + + + + + + + + + + + + + + 2015 + + + 2016 + + + 2017 + + + 2018 + + + + + + + + + + + + + + + + This is a Line chart + + + + + + + + + + + + + + + + + +
    +
    +
    + +`; + +exports[`renders title 1`] = ` + + This is a Line chart + +`; diff --git a/packages/react-charts/src/echarts/components/Line/examples/Basic.tsx b/packages/react-charts/src/echarts/components/Line/examples/Basic.tsx new file mode 100644 index 00000000000..22c5eef7997 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/examples/Basic.tsx @@ -0,0 +1,69 @@ +import { FunctionComponent } from 'react'; +import { Charts } from '@patternfly/react-charts/echarts'; + +import * as echarts from 'echarts/core'; +import { LineChart } from 'echarts/charts'; +import { GridComponent, TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([GridComponent, LineChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Basic: FunctionComponent = () => ( + (value !== 0 ? `${value}` : '') + }, + splitNumber: 3, + type: 'value' + }, + series: [ + { + data: [1, 2, 5, 3], + name: 'Cats', + type: 'line' + }, + { + data: [2, 1, 7, 4], + name: 'Dogs', + lineStyle: { + type: 'dashed' + }, + type: 'line' + }, + { + data: [3, 4, 9, 5], + name: 'Birds', + type: 'line' + }, + { + data: [3, 3, 8, 7], + name: 'Mice', + type: 'line' + } + ], + title: { + left: 'center', + text: 'This is a Line chart' + } + }} + width={825} + /> +); diff --git a/packages/react-charts/src/echarts/components/Line/examples/Responsive.tsx b/packages/react-charts/src/echarts/components/Line/examples/Responsive.tsx new file mode 100644 index 00000000000..7905aa65a0c --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/examples/Responsive.tsx @@ -0,0 +1,88 @@ +import { FunctionComponent, useEffect, useRef, useState } from 'react'; +import { Charts, ThemeColor } from '@patternfly/react-charts/echarts'; +import { getResizeObserver } from '@patternfly/react-core'; + +import * as echarts from 'echarts/core'; +import { LineChart } from 'echarts/charts'; +import { GridComponent, TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([GridComponent, LineChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Responsive: FunctionComponent = () => { + const containerRef = useRef(); + const [width, setWidth] = useState(0); + + useEffect(() => { + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + let observer = () => {}; + observer = getResizeObserver(containerRef.current, handleResize); + + return () => { + observer(); + }; + }, [containerRef, width]); + + return ( +
    + (value !== 0 ? `${value}` : '') + }, + splitNumber: 3, + type: 'value' + }, + series: [ + { + data: [1, 2, 5, 3], + name: 'Cats', + type: 'line' + }, + { + data: [2, 1, 7, 4], + name: 'Dogs', + lineStyle: { + type: 'dashed' + }, + type: 'line' + }, + { + data: [3, 4, 9, 5], + name: 'Birds', + type: 'line' + }, + { + data: [3, 3, 8, 7], + name: 'Mice', + type: 'line' + } + ], + title: { + left: 'center', + text: 'This is a Line chart', + type: 'line' + } + }} + themeColor={ThemeColor.green} + width={width} + /> +
    + ); +}; diff --git a/packages/react-charts/src/echarts/components/Line/examples/Skeleton.tsx b/packages/react-charts/src/echarts/components/Line/examples/Skeleton.tsx new file mode 100644 index 00000000000..f41a82d6ae7 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/examples/Skeleton.tsx @@ -0,0 +1,75 @@ +import { FormEvent, FunctionComponent, useState } from 'react'; +import { Charts, ThemeColor } from '@patternfly/react-charts/echarts'; +import { Switch } from '@patternfly/react-core'; + +import * as echarts from 'echarts/core'; +import { LineChart } from 'echarts/charts'; +import { GridComponent, TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([GridComponent, LineChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Skeleton: FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + + + + ); +}; diff --git a/packages/react-charts/src/echarts/components/Line/examples/Theme.tsx b/packages/react-charts/src/echarts/components/Line/examples/Theme.tsx new file mode 100644 index 00000000000..3b3225f5530 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/examples/Theme.tsx @@ -0,0 +1,92 @@ +import { FunctionComponent } from 'react'; +import { getComputedStyleValue, getCustomTheme, Charts, ThemeColor } from '@patternfly/react-charts/echarts'; + +import * as echarts from 'echarts/core'; +import { LineChart } from 'echarts/charts'; +import { GridComponent, TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; +import chart_color_teal_300 from '@patternfly/react-tokens/dist/esm/chart_color_teal_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; + +// Register required components +echarts.use([GridComponent, LineChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Theme: FunctionComponent = () => { + const myCustomTheme = getCustomTheme(ThemeColor.default, { + color: [ + getComputedStyleValue(chart_color_purple_300), + getComputedStyleValue(chart_color_blue_300), + getComputedStyleValue(chart_color_green_300), + getComputedStyleValue(chart_color_teal_300), + getComputedStyleValue(chart_color_yellow_300) + ] + }); + + return ( + (value !== 0 ? `${value}` : '') + }, + splitNumber: 3, + type: 'value' + }, + series: [ + { + data: [1, 2, 5, 3], + name: 'Cats', + symbol: 'rect', + type: 'line' + }, + { + data: [2, 1, 7, 4], + name: 'Dogs', + lineStyle: { + type: 'dashed' + }, + symbol: 'arrow', + type: 'line' + }, + { + data: [3, 4, 9, 5], + name: 'Birds', + symbol: 'circle', + type: 'line' + }, + { + data: [3, 3, 8, 7], + name: 'Mice', + symbol: 'emptyCircle', + type: 'line' + } + ], + title: { + left: 'center', + text: 'This is a Line chart' + } + }} + theme={myCustomTheme} + width={825} + /> + ); +}; diff --git a/packages/react-charts/src/echarts/components/Line/examples/index.md b/packages/react-charts/src/echarts/components/Line/examples/index.md new file mode 100644 index 00000000000..c440cf73d37 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/examples/index.md @@ -0,0 +1,62 @@ +--- +id: Line chart +section: components +subsection: charts +propComponents: [ + { + component: 'Charts', + source: 'ECharts-docs' + }, + { + component: 'ChartsOptionProps', + source: 'ECharts-docs' + }, + { + component: 'TooltipOptionProps', + source: 'ECharts-docs' + } +] +beta: true +--- +import { FunctionComponent, useEffect, useRef, useState } from 'react'; +import * as echarts from 'echarts'; +import { LineChart } from 'echarts/charts'; +import { GridComponent, TitleComponent, ToolboxComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; +import { getComputedStyleValue, getCustomTheme, Charts, ThemeColor } from '@patternfly/react-charts/echarts'; + +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; +import chart_color_teal_300 from '@patternfly/react-tokens/dist/esm/chart_color_teal_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Apache ECharts](https://echarts.apache.org/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic with right aligned legend + +```ts file="./Basic.tsx" + +``` + +### Green with responsive container and bottom aligned legend +```ts file="./Responsive.tsx" + +``` + +### Custom theme +This demonstrates how to create a color scale via a custom theme, which may be applied to multiple charts. + +```ts file="./Theme.tsx" + +``` + +### Skeleton + +```ts file="./Skeleton.tsx" + +``` diff --git a/packages/react-charts/src/echarts/components/Line/index.ts b/packages/react-charts/src/echarts/components/Line/index.ts new file mode 100644 index 00000000000..34a969a3d62 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Line/index.ts @@ -0,0 +1 @@ +export * from './Line'; diff --git a/packages/react-charts/src/echarts/components/Sankey/Sankey.tsx b/packages/react-charts/src/echarts/components/Sankey/Sankey.tsx new file mode 100644 index 00000000000..5fd03095354 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/Sankey.tsx @@ -0,0 +1,32 @@ +import defaultsDeep from 'lodash/defaultsDeep'; + +import { ThemeDefinition } from '../themes/Theme'; + +/** + * Returns series properties for Sankey chart + * + * @param serie + * @param theme + * @param isSkeleton + * @private Not intended as public API and subject to change + */ +export const getSankeySeries = (serie: any, theme: ThemeDefinition, isSkeleton: boolean) => { + const defaults = { + data: serie.data.map((datum: any, index: number) => ({ + itemStyle: { + color: theme?.color[index % theme?.color.length] + } + })), + ...(isSkeleton ? { draggable: false } : {}), + emphasis: { + ...(isSkeleton ? { disabled: true } : { focus: 'adjacency' }) + }, + layout: 'none', + lineStyle: { + color: 'source', + opacity: 0.6 + }, + type: 'sankey' + }; + return defaultsDeep(serie, defaults); +}; diff --git a/packages/react-charts/src/echarts/components/Sankey/__tests__/Sankey.test.tsx b/packages/react-charts/src/echarts/components/Sankey/__tests__/Sankey.test.tsx new file mode 100644 index 00000000000..a0910906a2f --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/__tests__/Sankey.test.tsx @@ -0,0 +1,109 @@ +import { setupJestCanvasMock } from 'jest-canvas-mock'; +import { render, screen } from '@testing-library/react'; +import { Charts } from '../../Charts'; + +import * as echarts from 'echarts/core'; +import { SankeyChart } from 'echarts/charts'; +import { TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([SankeyChart, SVGRenderer, TitleComponent, TooltipComponent]); + +beforeEach(() => { + jest.resetAllMocks(); + jest.mock('echarts'); + setupJestCanvasMock(); +}); + +const data = [ + { + name: 'a' + }, + { + name: 'b' + }, + { + name: 'a1' + }, + { + name: 'a2' + }, + { + name: 'b1' + }, + { + name: 'c' + } +]; + +const links = [ + { + source: 'a', + target: 'a1', + value: 5 + }, + { + source: 'a', + target: 'a2', + value: 3 + }, + { + source: 'b', + target: 'b1', + value: 8 + }, + { + source: 'a', + target: 'b1', + value: 3 + }, + { + source: 'b1', + target: 'a1', + value: 1 + }, + { + source: 'b1', + target: 'c', + value: 2 + } +]; + +const props: any = { + height: 400, + id: 'sankey-chart', + option: { + series: [{ data, links, type: 'sankey' }], + title: { + text: 'This is a Sankey chart' + } + }, + width: 800 +}; + +// Remove dynamic _echarts_instance_ ID +const removeInstanceID = (fragment) => { + fragment.getElementById('sankey-chart').removeAttribute('_echarts_instance_'); + return fragment; +}; + +test('renders component', () => { + const { asFragment } = render(); + expect(removeInstanceID(asFragment())).toMatchSnapshot(); +}); + +test('renders title', async () => { + render(); + + const title = await screen.findByText(props.option.title.text); + expect(title).toMatchSnapshot(); +}); + +test('renders height and width', async () => { + const { asFragment } = render(); + + const svg = asFragment().querySelector('svg'); + expect(svg).toHaveAttribute('height', `${props.height}`); + expect(svg).toHaveAttribute('width', `${props.width}`); +}); diff --git a/packages/react-charts/src/echarts/components/Sankey/__tests__/__snapshots__/Sankey.test.tsx.snap b/packages/react-charts/src/echarts/components/Sankey/__tests__/__snapshots__/Sankey.test.tsx.snap new file mode 100644 index 00000000000..7cf03d7d4a6 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/__tests__/__snapshots__/Sankey.test.tsx.snap @@ -0,0 +1,218 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders component 1`] = ` + +
    +
    + + + + + + + + + + + + + + + + + + a + + + b + + + a1 + + + a2 + + + b1 + + + c + + + + + This is a Sankey chart + + + + + + + + +
    +
    +
    + +`; + +exports[`renders title 1`] = ` + + This is a Sankey chart + +`; diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/Basic.tsx b/packages/react-charts/src/echarts/components/Sankey/examples/Basic.tsx new file mode 100644 index 00000000000..f970a3b137f --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/examples/Basic.tsx @@ -0,0 +1,87 @@ +import { FunctionComponent } from 'react'; +import { Charts } from '@patternfly/react-charts/echarts'; + +import * as echarts from 'echarts/core'; +import { SankeyChart } from 'echarts/charts'; +import { TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([SankeyChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Basic: FunctionComponent = () => { + const data = [ + { + name: 'a' + }, + { + name: 'b' + }, + { + name: 'a1' + }, + { + name: 'a2' + }, + { + name: 'b1' + }, + { + name: 'c' + } + ]; + + const links = [ + { + source: 'a', + target: 'a1', + value: 5 + }, + { + source: 'a', + target: 'a2', + value: 3 + }, + { + source: 'b', + target: 'b1', + value: 8 + }, + { + source: 'a', + target: 'b1', + value: 3 + }, + { + source: 'b1', + target: 'a1', + value: 1 + }, + { + source: 'b1', + target: 'c', + value: 2 + } + ]; + + return ( + `${value} GiB` + } + }} + width={825} + /> + ); +}; diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/Responsive.tsx b/packages/react-charts/src/echarts/components/Sankey/examples/Responsive.tsx new file mode 100644 index 00000000000..778cc25cca1 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/examples/Responsive.tsx @@ -0,0 +1,108 @@ +import { FunctionComponent, useEffect, useRef, useState } from 'react'; +import { Charts, ThemeColor } from '@patternfly/react-charts/echarts'; +import { getResizeObserver } from '@patternfly/react-core'; + +import * as echarts from 'echarts/core'; +import { SankeyChart } from 'echarts/charts'; +import { TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([SankeyChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Responsive: FunctionComponent = () => { + const data = [ + { + name: 'a' + }, + { + name: 'b' + }, + { + name: 'a1' + }, + { + name: 'a2' + }, + { + name: 'b1' + }, + { + name: 'c' + } + ]; + + const links = [ + { + source: 'a', + target: 'a1', + value: 5 + }, + { + source: 'a', + target: 'a2', + value: 3 + }, + { + source: 'b', + target: 'b1', + value: 8 + }, + { + source: 'a', + target: 'b1', + value: 3 + }, + { + source: 'b1', + target: 'a1', + value: 1 + }, + { + source: 'b1', + target: 'c', + value: 2 + } + ]; + + const containerRef = useRef(); + const [width, setWidth] = useState(0); + + useEffect(() => { + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + let observer = () => {}; + observer = getResizeObserver(containerRef.current, handleResize); + + return () => { + observer(); + }; + }, [containerRef, width]); + + return ( +
    + `${value} GiB` + } + }} + themeColor={ThemeColor.multiUnordered} + width={width} + /> +
    + ); +}; diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/Skeleton.tsx b/packages/react-charts/src/echarts/components/Sankey/examples/Skeleton.tsx new file mode 100644 index 00000000000..ef0b126c05f --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/examples/Skeleton.tsx @@ -0,0 +1,98 @@ +import { FormEvent, FunctionComponent, useState } from 'react'; +import { Charts, ThemeColor } from '@patternfly/react-charts/echarts'; +import { Switch } from '@patternfly/react-core'; + +import * as echarts from 'echarts/core'; +import { SankeyChart } from 'echarts/charts'; +import { TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([SankeyChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Skeleton: FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const data = [ + { + name: 'a' + }, + { + name: 'b' + }, + { + name: 'a1' + }, + { + name: 'a2' + }, + { + name: 'b1' + }, + { + name: 'c' + } + ]; + + const links = [ + { + source: 'a', + target: 'a1', + value: 5 + }, + { + source: 'a', + target: 'a2', + value: 3 + }, + { + source: 'b', + target: 'b1', + value: 8 + }, + { + source: 'a', + target: 'b1', + value: 3 + }, + { + source: 'b1', + target: 'a1', + value: 1 + }, + { + source: 'b1', + target: 'c', + value: 2 + } + ]; + + return ( + <> + + `${value} GiB` + } + }} + themeColor={isChecked ? ThemeColor.skeleton : ThemeColor.green} + width={825} + /> + + ); +}; diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/Theme.tsx b/packages/react-charts/src/echarts/components/Sankey/examples/Theme.tsx new file mode 100644 index 00000000000..3f2963ae149 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/examples/Theme.tsx @@ -0,0 +1,104 @@ +import { FunctionComponent } from 'react'; +import { getComputedStyleValue, getCustomTheme, Charts, ThemeColor } from '@patternfly/react-charts/echarts'; + +import * as echarts from 'echarts/core'; +import { SankeyChart } from 'echarts/charts'; +import { TitleComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; +import chart_color_teal_300 from '@patternfly/react-tokens/dist/esm/chart_color_teal_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; + +// Register required components +echarts.use([SankeyChart, SVGRenderer, TitleComponent, TooltipComponent]); + +export const Theme: FunctionComponent = () => { + const data = [ + { + name: 'a' + }, + { + name: 'b' + }, + { + name: 'a1' + }, + { + name: 'a2' + }, + { + name: 'b1' + }, + { + name: 'c' + } + ]; + + const links = [ + { + source: 'a', + target: 'a1', + value: 5 + }, + { + source: 'a', + target: 'a2', + value: 3 + }, + { + source: 'b', + target: 'b1', + value: 8 + }, + { + source: 'a', + target: 'b1', + value: 3 + }, + { + source: 'b1', + target: 'a1', + value: 1 + }, + { + source: 'b1', + target: 'c', + value: 2 + } + ]; + + const myCustomTheme = getCustomTheme(ThemeColor.default, { + color: [ + getComputedStyleValue(chart_color_purple_300), + getComputedStyleValue(chart_color_blue_300), + getComputedStyleValue(chart_color_green_300), + getComputedStyleValue(chart_color_teal_300), + getComputedStyleValue(chart_color_yellow_300) + ] + }); + + return ( + `${value} GiB` + } + }} + theme={myCustomTheme} + width={825} + /> + ); +}; diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/Toolbox.tsx b/packages/react-charts/src/echarts/components/Sankey/examples/Toolbox.tsx new file mode 100644 index 00000000000..73453276ba6 --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/examples/Toolbox.tsx @@ -0,0 +1,117 @@ +import { FunctionComponent, useEffect, useRef, useState } from 'react'; +import { Charts, ThemeColor } from '@patternfly/react-charts/echarts'; +import { getResizeObserver } from '@patternfly/react-core'; + +import * as echarts from 'echarts/core'; +import { SankeyChart } from 'echarts/charts'; +import { TitleComponent, ToolboxComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; + +// Register required components +echarts.use([SankeyChart, SVGRenderer, TitleComponent, ToolboxComponent, TooltipComponent]); + +export const Toolbox: FunctionComponent = () => { + const data = [ + { + name: 'a' + }, + { + name: 'b' + }, + { + name: 'a1' + }, + { + name: 'a2' + }, + { + name: 'b1' + }, + { + name: 'c' + } + ]; + + const links = [ + { + source: 'a', + target: 'a1', + value: 5 + }, + { + source: 'a', + target: 'a2', + value: 3 + }, + { + source: 'b', + target: 'b1', + value: 8 + }, + { + source: 'a', + target: 'b1', + value: 3 + }, + { + source: 'b1', + target: 'a1', + value: 1 + }, + { + source: 'b1', + target: 'c', + value: 2 + } + ]; + + // let observer = () => {}; + const containerRef = useRef(); + const [width, setWidth] = useState(0); + + useEffect(() => { + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + let observer = () => {}; + observer = getResizeObserver(containerRef.current, handleResize); + + return () => { + observer(); + }; + }, [containerRef, width]); + + return ( +
    + `${value} GiB` + } + }} + themeColor={ThemeColor.teal} + width={width} + /> +
    + ); +}; diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/index.md b/packages/react-charts/src/echarts/components/Sankey/examples/index.md new file mode 100644 index 00000000000..26670100e7f --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/examples/index.md @@ -0,0 +1,72 @@ +--- +id: Sankey chart +section: components +subsection: charts +propComponents: [ + { + component: 'Charts', + source: 'ECharts-docs' + }, + { + component: 'ChartsOptionProps', + source: 'ECharts-docs' + }, + { + component: 'TooltipOptionProps', + source: 'ECharts-docs' + } +] +beta: true +--- + +import { FunctionComponent, useEffect, useRef, useState } from 'react'; +import * as echarts from 'echarts'; +import { SankeyChart } from 'echarts/charts'; +import { TitleComponent, ToolboxComponent, TooltipComponent } from 'echarts/components'; +import { SVGRenderer } from 'echarts/renderers'; +import { getComputedStyleValue, getCustomTheme, Charts, ThemeColor } from '@patternfly/react-charts/echarts'; + +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; +import chart_color_teal_300 from '@patternfly/react-tokens/dist/esm/chart_color_teal_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Apache ECharts](https://echarts.apache.org/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic + +```ts file="./Basic.tsx" + +``` + +### Multi-color (unordered) with responsive container + +```ts file="./Responsive.tsx" + +``` + +### Teal color with responsive container and toolbox + +This demonstrates how to import `ToolboxComponent` for use with ECharts + +```ts file="./Toolbox.tsx" + +``` + +### Custom theme +This demonstrates how to create a color scale via a custom theme, which may be applied to multiple charts. + +```ts file="./Theme.tsx" + +``` + +### Skeleton + +```ts file="./Skeleton.tsx" + +``` diff --git a/packages/react-charts/src/echarts/components/Sankey/index.ts b/packages/react-charts/src/echarts/components/Sankey/index.ts new file mode 100644 index 00000000000..4bb44aaee6a --- /dev/null +++ b/packages/react-charts/src/echarts/components/Sankey/index.ts @@ -0,0 +1 @@ +export * from './Sankey'; diff --git a/packages/react-charts/src/echarts/components/index.ts b/packages/react-charts/src/echarts/components/index.ts new file mode 100644 index 00000000000..45429a5ccd4 --- /dev/null +++ b/packages/react-charts/src/echarts/components/index.ts @@ -0,0 +1,4 @@ +export * from './Charts'; +export * from './themes/ThemeColor'; +export { getCustomTheme, getTheme } from './utils/theme'; +export { getComputedStyleValue } from './utils/styles'; diff --git a/packages/react-charts/src/echarts/components/themes/Theme.ts b/packages/react-charts/src/echarts/components/themes/Theme.ts new file mode 100644 index 00000000000..07e6787b6c4 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/Theme.ts @@ -0,0 +1,15 @@ +import { ThemeOption } from 'echarts/types/src/util/types'; + +/** + * Theme definition interface + * + * @public + */ +export interface ThemeDefinitionInterface extends ThemeOption {} + +/** + * Theme definition type + * + * @public + */ +export type ThemeDefinition = ThemeDefinitionInterface; diff --git a/packages/react-charts/src/echarts/components/themes/ThemeColor.ts b/packages/react-charts/src/echarts/components/themes/ThemeColor.ts new file mode 100644 index 00000000000..15cb8830f2b --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/ThemeColor.ts @@ -0,0 +1,55 @@ +interface ThemeColorInterface { + blue: string; + teal: string; + default: string; + yellow: string; + gray: string; + green: string; + multi: string; + multiOrdered: string; + multiUnordered: string; + orange: string; + purple: string; + skeleton: string; +} + +/** + * The color family to be applied to a theme. For example, 'blue' represents an ordered list of colors + * (i.e., a color scale) composed of the blue color family defined by PatternFly core. + * + * For example, the 'blue' color scale looks like: + * + * chart_color_blue_100 + * chart_color_blue_200 + * chart_color_blue_300 + * chart_color_blue_400 + * chart_color_blue_500 + * + * In this case, the chart_color_blue_100 value would be applied to the first data point in a chart. + * The chart_color_blue_200 value would be applied to the second data point in a chart. And so on... + * + * If legend data is provided to a chart, those colors would be synced with the legend as well. + * + * The 'multiOrdered' color family is intended for ordered charts; donut, pie, bar, & stack + * The 'multiUnordered' color family is intended for unordered charts; area & line + * The 'multi' defaults to the 'multiOrdered' color family + * + * Note: These values are not intended to be applied directly as a component's fill style. For example, "multi" would + * not be a valid fill color. Please use chart variables from PatternFly core (e.g., via the react-charts package) + * + * @public + */ +export const ThemeColor: ThemeColorInterface = { + blue: 'blue', + teal: 'teal', + default: 'blue', + yellow: 'yellow', + gray: 'gray', + green: 'green', + multi: 'multi', + multiOrdered: 'multi-ordered', + multiUnordered: 'multi-unordered', + orange: 'orange', + purple: 'purple', + skeleton: 'skeleton' +}; diff --git a/packages/react-charts/src/echarts/components/themes/base-theme.ts b/packages/react-charts/src/echarts/components/themes/base-theme.ts new file mode 100644 index 00000000000..d69479efbb5 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/base-theme.ts @@ -0,0 +1,252 @@ +import chart_echarts_bar_item_style_BarBorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_bar_item_style_BarBorderColor'; +import chart_echarts_boxplot_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_boxplot_item_style_BorderWidth'; +import chart_echarts_candlestick_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_candlestick_item_style_BorderWidth'; +import chart_echarts_datazoom_HandleSize from '@patternfly/react-tokens/dist/esm/chart_echarts_datazoom_HandleSize'; +import chart_echarts_funnel_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_funnel_item_style_BorderWidth'; +import chart_echarts_gauge_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_gauge_item_style_BorderWidth'; +import chart_echarts_geo_emphasis_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_gauge_item_style_BorderWidth'; +import chart_echarts_geo_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_gauge_item_style_BorderWidth'; +import chart_echarts_global_axis_BoundaryGap from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_BoundaryGap'; +import chart_echarts_global_axis_axis_label_Show from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_axis_label_Show'; +import chart_echarts_global_axis_axis_line_Show from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_axis_line_Show'; +import chart_echarts_global_axis_axis_tick_Show from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_axis_tick_Show'; +import chart_echarts_global_axis_split_area_Show from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_split_area_Show'; +import chart_echarts_global_axis_split_line_Show from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_split_line_Show'; +import chart_echarts_graph_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_graph_item_style_BorderWidth'; +import chart_echarts_graph_line_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_graph_line_style_BorderWidth'; +import chart_echarts_graph_Smooth from '@patternfly/react-tokens/dist/esm/chart_echarts_graph_Smooth'; +import chart_echarts_graph_Symbol from '@patternfly/react-tokens/dist/esm/chart_echarts_graph_Symbol'; +import chart_echarts_graph_SymbolSize from '@patternfly/react-tokens/dist/esm/chart_echarts_graph_SymbolSize'; +import chart_echarts_line_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_line_item_style_BorderWidth'; +import chart_echarts_line_line_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_line_line_style_BorderWidth'; +import chart_echarts_line_Smooth from '@patternfly/react-tokens/dist/esm/chart_echarts_line_Smooth'; +import chart_echarts_line_Symbol from '@patternfly/react-tokens/dist/esm/chart_echarts_line_Symbol'; +import chart_echarts_line_SymbolSize from '@patternfly/react-tokens/dist/esm/chart_echarts_line_SymbolSize'; +import chart_echarts_map_emphasis_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_map_emphasis_item_style_BorderWidth'; +import chart_echarts_map_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_map_item_style_BorderWidth'; +import chart_echarts_parallel_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_parallel_item_style_BorderWidth'; +import chart_echarts_pie_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_pie_item_style_BorderWidth'; +import chart_echarts_radar_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_radar_item_style_BorderWidth'; +import chart_echarts_radar_line_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_radar_line_style_BorderWidth'; +import chart_echarts_radar_Smooth from '@patternfly/react-tokens/dist/esm/chart_echarts_radar_Smooth'; +import chart_echarts_radar_Symbol from '@patternfly/react-tokens/dist/esm/chart_echarts_radar_Symbol'; +import chart_echarts_radar_SymbolSize from '@patternfly/react-tokens/dist/esm/chart_echarts_radar_SymbolSize'; +import chart_echarts_sankey_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_sankey_item_style_BorderWidth'; +import chart_echarts_scatter_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_scatter_item_style_BorderWidth'; +import chart_echarts_timeline_control_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_control_style_BorderWidth'; +import chart_echarts_timeline_emphasis_control_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_emphasis_control_style_BorderWidth'; +import chart_echarts_timeline_item_style_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_item_style_BorderWidth'; +import chart_echarts_timeline_line_style_Width from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_line_style_Width'; +import chart_echarts_tooltip_axis_pointer_cross_style_Width from '@patternfly/react-tokens/dist/esm/chart_echarts_tooltip_axis_pointer_cross_style_Width'; +import chart_echarts_tooltip_axis_pointer_line_style_Width from '@patternfly/react-tokens/dist/esm/chart_echarts_tooltip_axis_pointer_line_style_Width'; +import chart_global_FontFamily from '@patternfly/react-tokens/dist/esm/chart_global_FontFamily'; +import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; + +import { ThemeDefinition } from './Theme'; +import { getComputedStyleValue } from '../utils/styles'; + +/** + * Base theme containing EChart properties only + * + * @private Not intended as public API and subject to change + */ +export const BaseTheme = (): ThemeDefinition => { + const textProps = { + fontFamily: chart_global_FontFamily.var.replace(/"/g, "'"), // Well-formed XML + fontSize: chart_global_FontSize_sm.value + }; + + const axisProps = { + boundaryGap: getComputedStyleValue(chart_echarts_global_axis_BoundaryGap), + axisLabel: { + ...textProps, + show: getComputedStyleValue(chart_echarts_global_axis_axis_label_Show) + }, + axisLine: { + lineStyle: {}, + show: getComputedStyleValue(chart_echarts_global_axis_axis_line_Show) + }, + axisTick: { + lineStyle: {}, + show: getComputedStyleValue(chart_echarts_global_axis_axis_tick_Show) + }, + splitArea: { + areaStyle: {}, + show: getComputedStyleValue(chart_echarts_global_axis_split_area_Show) + }, + splitLine: { + lineStyle: {}, + show: getComputedStyleValue(chart_echarts_global_axis_split_line_Show) // Grid + } + }; + + return { + bar: { + itemStyle: { + barBorderWidth: getComputedStyleValue(chart_echarts_bar_item_style_BarBorderWidth) + } + }, + boxplot: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_boxplot_item_style_BorderWidth) + } + }, + candlestick: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_candlestick_item_style_BorderWidth) + } + }, + categoryAxis: { ...axisProps }, + dataZoom: { + handleSize: getComputedStyleValue(chart_echarts_datazoom_HandleSize), + textStyle: { ...textProps } + }, + funnel: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_funnel_item_style_BorderWidth) + } + }, + gauge: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_gauge_item_style_BorderWidth) + } + }, + geo: { + emphasis: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_geo_emphasis_item_style_BorderWidth) + }, + label: {} + }, + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_geo_item_style_BorderWidth) + }, + label: {} + }, + graph: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_graph_item_style_BorderWidth) + }, + label: {}, + lineStyle: { + width: getComputedStyleValue(chart_echarts_graph_line_style_BorderWidth) + }, + smooth: getComputedStyleValue(chart_echarts_graph_Smooth), + symbolSize: getComputedStyleValue(chart_echarts_graph_SymbolSize), + symbol: getComputedStyleValue(chart_echarts_graph_Symbol) + }, + label: { + ...textProps + }, + legend: { + textStyle: { ...textProps } + }, + line: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_line_item_style_BorderWidth) + }, + lineStyle: { + width: getComputedStyleValue(chart_echarts_line_line_style_BorderWidth) + }, + smooth: getComputedStyleValue(chart_echarts_line_Smooth), + symbolSize: getComputedStyleValue(chart_echarts_line_SymbolSize), + symbol: getComputedStyleValue(chart_echarts_line_Symbol) + }, + logAxis: { ...axisProps }, + map: { + emphasis: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_map_emphasis_item_style_BorderWidth) + }, + label: {} + }, + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_map_item_style_BorderWidth) + }, + label: { + label: {} + } + }, + markPoint: { + emphasis: { + label: {} + }, + label: {} + }, + parallel: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_parallel_item_style_BorderWidth) + } + }, + pie: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_pie_item_style_BorderWidth) + } + }, + radar: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_radar_item_style_BorderWidth) + }, + lineStyle: { + width: getComputedStyleValue(chart_echarts_radar_line_style_BorderWidth) + }, + smooth: getComputedStyleValue(chart_echarts_radar_Smooth), + symbolSize: getComputedStyleValue(chart_echarts_radar_SymbolSize), + symbol: getComputedStyleValue(chart_echarts_radar_Symbol) + }, + sankey: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_sankey_item_style_BorderWidth) + } + }, + scatter: { + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_scatter_item_style_BorderWidth) + } + }, + textStyle: { ...textProps }, + timeAxis: { ...axisProps }, + timeline: { + emphasis: { + controlStyle: { + borderWidth: getComputedStyleValue(chart_echarts_timeline_emphasis_control_style_BorderWidth) + }, + itemStyle: {}, + label: {} + }, + checkpointStyle: {}, + controlStyle: { + borderWidth: getComputedStyleValue(chart_echarts_timeline_control_style_BorderWidth) + }, + itemStyle: { + borderWidth: getComputedStyleValue(chart_echarts_timeline_item_style_BorderWidth) + }, + label: {}, + lineStyle: { + width: getComputedStyleValue(chart_echarts_timeline_line_style_Width) + } + }, + title: { + subtextStyle: { ...textProps }, + textStyle: { ...textProps } + }, + toolbox: { + emphasis: { + iconStyle: {} + }, + iconStyle: {} + }, + tooltip: { + axisPointer: { + crossStyle: { + width: getComputedStyleValue(chart_echarts_tooltip_axis_pointer_cross_style_Width) + }, + lineStyle: { + width: getComputedStyleValue(chart_echarts_tooltip_axis_pointer_line_style_Width) + } + } + }, + valueAxis: { ...axisProps }, + visualMap: {} + }; +}; diff --git a/packages/react-charts/src/echarts/components/themes/color-theme.ts b/packages/react-charts/src/echarts/components/themes/color-theme.ts new file mode 100644 index 00000000000..e53ae0e3679 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/color-theme.ts @@ -0,0 +1,252 @@ +import chart_echarts_BackgroundColor from '@patternfly/react-tokens/dist/esm/chart_echarts_BackgroundColor'; +import chart_echarts_bar_item_style_BarBorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_bar_item_style_BarBorderColor'; +import chart_echarts_boxplot_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_boxplot_item_style_BorderColor'; +import chart_echarts_candlestick_item_style_positive_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_candlestick_item_style_positive_BorderColor'; +import chart_echarts_candlestick_item_style_positive_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_candlestick_item_style_positive_Color'; +import chart_echarts_candlestick_item_style_negative_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_candlestick_item_style_negative_Color'; +import chart_echarts_candlestick_item_style_negative_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_candlestick_item_style_negative_BorderColor'; +import chart_echarts_funnel_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_funnel_item_style_BorderColor'; +import chart_echarts_gauge_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_gauge_item_style_BorderColor'; +import chart_echarts_geo_emphasis_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_geo_emphasis_item_style_BorderColor'; +import chart_echarts_geo_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_geo_item_style_BorderColor'; +import chart_echarts_global_axis_axis_line_item_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_axis_line_item_style_Color'; +import chart_echarts_global_axis_axis_tick_item_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_axis_tick_item_style_Color'; +import chart_echarts_global_axis_split_area_area_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_split_area_area_style_Color'; +import chart_echarts_global_label_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_global_label_Color'; +import chart_echarts_graph_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_graph_item_style_BorderColor'; +import chart_echarts_graph_line_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_graph_line_style_Color'; +import chart_echarts_map_emphasis_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_map_emphasis_item_style_BorderColor'; +import chart_echarts_map_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_map_item_style_BorderColor'; +import chart_echarts_parallel_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_parallel_item_style_BorderColor'; +import chart_echarts_pie_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_pie_item_style_BorderColor'; +import chart_echarts_sankey_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_sankey_item_style_BorderColor'; +import chart_echarts_scatter_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_scatter_item_style_BorderColor'; +import chart_echarts_tooltip_axis_pointer_cross_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_tooltip_axis_pointer_cross_style_Color'; +import chart_echarts_tooltip_axis_pointer_line_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_tooltip_axis_pointer_line_style_Color'; +import chart_echarts_toolbox_emphasis_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_toolbox_emphasis_item_style_BorderColor'; +import chart_echarts_toolbox_item_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_toolbox_item_style_BorderColor'; +import chart_echarts_timeline_emphasis_control_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_emphasis_control_style_Color'; +import chart_echarts_timeline_emphasis_item_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_emphasis_item_style_Color'; +import chart_echarts_timeline_emphasis_control_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_emphasis_control_style_BorderColor'; +import chart_echarts_timeline_checkpoint_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_checkpoint_style_Color'; +import chart_echarts_timeline_checkpoint_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_checkpoint_style_BorderColor'; +import chart_echarts_timeline_control_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_control_style_Color'; +import chart_echarts_timeline_control_style_BorderColor from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_control_style_BorderColor'; +import chart_echarts_timeline_item_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_item_style_Color'; +import chart_echarts_timeline_line_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_timeline_line_style_Color'; +import chart_echarts_tooltip_backgroundColor from '@patternfly/react-tokens/dist/esm/chart_echarts_tooltip_backgroundColor'; +import chart_echarts_tooltip_text_Style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_tooltip_text_Style_Color'; + +import { ThemeDefinition } from './Theme'; +import { getComputedStyleValue } from '../utils/styles'; + +interface ColorThemeInterface { + COLOR_SCALE: string[]; +} + +/** + * ECharts color theme + * + * @private Not intended as public API and subject to change + * @beta + */ +export const ColorTheme = (props: ColorThemeInterface): ThemeDefinition => { + const { COLOR_SCALE } = props; + + const labelProps = { + color: getComputedStyleValue(chart_echarts_global_label_Color) + }; + + const axisProps = { + axisLabel: { ...labelProps }, + axisLine: { + lineStyle: { + color: getComputedStyleValue(chart_echarts_global_axis_axis_line_item_style_Color) + } + }, + axisTick: { + lineStyle: { + color: getComputedStyleValue(chart_echarts_global_axis_axis_tick_item_style_Color) + } + }, + splitArea: { + areaStyle: { + color: getComputedStyleValue(chart_echarts_global_axis_split_area_area_style_Color) + } + }, + splitLine: { + lineStyle: { + color: getComputedStyleValue(chart_echarts_global_axis_axis_tick_item_style_Color) // Grid + } + } + }; + + return { + color: COLOR_SCALE, // See https://echarts.apache.org/en/option.html#color + backgroundColor: getComputedStyleValue(chart_echarts_BackgroundColor), // See https://echarts.apache.org/en/option.html#backgroundColor + bar: { + itemStyle: { + barBorderColor: getComputedStyleValue(chart_echarts_bar_item_style_BarBorderColor) + } + }, + boxplot: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_boxplot_item_style_BorderColor) + } + }, + candlestick: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_candlestick_item_style_negative_BorderColor), + borderColor0: getComputedStyleValue(chart_echarts_candlestick_item_style_positive_BorderColor), + color: getComputedStyleValue(chart_echarts_candlestick_item_style_negative_Color), + color0: getComputedStyleValue(chart_echarts_candlestick_item_style_positive_Color) + } + }, + categoryAxis: { ...axisProps }, + dataZoom: {}, + funnel: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_funnel_item_style_BorderColor) + } + }, + gauge: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_gauge_item_style_BorderColor) + } + }, + geo: { + emphasis: { + itemStyle: { + areaColor: COLOR_SCALE[1], + borderColor: getComputedStyleValue(chart_echarts_geo_emphasis_item_style_BorderColor) + }, + label: { ...labelProps } + }, + itemStyle: { + areaColor: COLOR_SCALE[0], + borderColor: getComputedStyleValue(chart_echarts_geo_item_style_BorderColor) + }, + label: { ...labelProps } + }, + graph: { + color: COLOR_SCALE, + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_graph_item_style_BorderColor) + }, + label: { ...labelProps }, + lineStyle: { + color: getComputedStyleValue(chart_echarts_graph_line_style_Color) + } + }, + label: { ...labelProps }, + legend: { + textStyle: { + color: getComputedStyleValue(chart_echarts_global_label_Color) + } + }, + line: {}, + logAxis: { ...axisProps }, + map: { + emphasis: { + itemStyle: { + areaColor: COLOR_SCALE[1], + borderColor: getComputedStyleValue(chart_echarts_map_emphasis_item_style_BorderColor) + }, + label: { ...labelProps } + }, + itemStyle: { + areaColor: COLOR_SCALE[0], + borderColor: getComputedStyleValue(chart_echarts_map_item_style_BorderColor) + }, + label: { ...labelProps } + }, + markPoint: { + emphasis: { + label: { ...labelProps } + }, + label: { ...labelProps } + }, + parallel: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_parallel_item_style_BorderColor) + } + }, + pie: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_pie_item_style_BorderColor) + } + }, + radar: {}, + sankey: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_sankey_item_style_BorderColor) + } + }, + scatter: { + itemStyle: { + borderColor: getComputedStyleValue(chart_echarts_scatter_item_style_BorderColor) + } + }, + textStyle: {}, + timeAxis: { ...axisProps }, + timeline: { + emphasis: { + controlStyle: { + color: getComputedStyleValue(chart_echarts_timeline_emphasis_control_style_Color), + borderColor: getComputedStyleValue(chart_echarts_timeline_emphasis_control_style_BorderColor) + }, + itemStyle: { + color: getComputedStyleValue(chart_echarts_timeline_emphasis_item_style_Color) + }, + label: { ...labelProps } + }, + checkpointStyle: { + color: getComputedStyleValue(chart_echarts_timeline_checkpoint_style_Color), + borderColor: getComputedStyleValue(chart_echarts_timeline_checkpoint_style_BorderColor) + }, + controlStyle: { + color: getComputedStyleValue(chart_echarts_timeline_control_style_Color), + borderColor: getComputedStyleValue(chart_echarts_timeline_control_style_BorderColor) + }, + itemStyle: { + color: getComputedStyleValue(chart_echarts_timeline_item_style_Color) + }, + label: { ...labelProps }, + lineStyle: { + color: getComputedStyleValue(chart_echarts_timeline_line_style_Color) + } + }, + title: { + subtextStyle: { ...labelProps }, + textStyle: { ...labelProps } + }, + toolbox: { + emphasis: { + iconStyle: { + borderColor: getComputedStyleValue(chart_echarts_toolbox_emphasis_item_style_BorderColor) + } + }, + iconStyle: { + borderColor: getComputedStyleValue(chart_echarts_toolbox_item_style_BorderColor) + } + }, + tooltip: { + backgroundColor: getComputedStyleValue(chart_echarts_tooltip_backgroundColor), + axisPointer: { + crossStyle: { + color: getComputedStyleValue(chart_echarts_tooltip_axis_pointer_cross_style_Color) + }, + lineStyle: { + color: getComputedStyleValue(chart_echarts_tooltip_axis_pointer_line_style_Color) + } + }, + textStyle: { + color: getComputedStyleValue(chart_echarts_tooltip_text_Style_Color) + } + }, + valueAxis: { ...axisProps }, + visualMap: { + color: COLOR_SCALE + } + }; +}; diff --git a/packages/react-charts/src/echarts/components/themes/colors/blue-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/blue-theme.ts new file mode 100644 index 00000000000..e908cbf3f7e --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/blue-theme.ts @@ -0,0 +1,23 @@ +import chart_theme_blue_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_100'; +import chart_theme_blue_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_200'; +import chart_theme_blue_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_300'; +import chart_theme_blue_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_400'; +import chart_theme_blue_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Blue color theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getBlueColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_blue_ColorScale_100), + getComputedStyleValue(chart_theme_blue_ColorScale_200), + getComputedStyleValue(chart_theme_blue_ColorScale_300), + getComputedStyleValue(chart_theme_blue_ColorScale_400), + getComputedStyleValue(chart_theme_blue_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/gray-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/gray-theme.ts new file mode 100644 index 00000000000..e3b11d2d893 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/gray-theme.ts @@ -0,0 +1,23 @@ +import chart_theme_gray_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_100'; +import chart_theme_gray_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_200'; +import chart_theme_gray_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_300'; +import chart_theme_gray_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_400'; +import chart_theme_gray_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Gray color theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getGrayColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_gray_ColorScale_100), + getComputedStyleValue(chart_theme_gray_ColorScale_200), + getComputedStyleValue(chart_theme_gray_ColorScale_300), + getComputedStyleValue(chart_theme_gray_ColorScale_400), + getComputedStyleValue(chart_theme_gray_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/green-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/green-theme.ts new file mode 100644 index 00000000000..5d979253a81 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/green-theme.ts @@ -0,0 +1,23 @@ +import chart_theme_green_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_100'; +import chart_theme_green_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_200'; +import chart_theme_green_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_300'; +import chart_theme_green_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_400'; +import chart_theme_green_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Green color theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getGreenColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_green_ColorScale_100), + getComputedStyleValue(chart_theme_green_ColorScale_200), + getComputedStyleValue(chart_theme_green_ColorScale_300), + getComputedStyleValue(chart_theme_green_ColorScale_400), + getComputedStyleValue(chart_theme_green_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/multi-ordered-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/multi-ordered-theme.ts new file mode 100644 index 00000000000..3844eea21f7 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/multi-ordered-theme.ts @@ -0,0 +1,64 @@ +import chart_theme_multi_color_ordered_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_100'; +import chart_theme_multi_color_ordered_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_200'; +import chart_theme_multi_color_ordered_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_300'; +import chart_theme_multi_color_ordered_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_400'; +import chart_theme_multi_color_ordered_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_500'; +import chart_theme_multi_color_ordered_ColorScale_600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_600'; +import chart_theme_multi_color_ordered_ColorScale_700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_700'; +import chart_theme_multi_color_ordered_ColorScale_800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_800'; +import chart_theme_multi_color_ordered_ColorScale_900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_900'; +import chart_theme_multi_color_ordered_ColorScale_1000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1000'; +import chart_theme_multi_color_ordered_ColorScale_1100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1100'; +import chart_theme_multi_color_ordered_ColorScale_1200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1200'; +import chart_theme_multi_color_ordered_ColorScale_1300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1300'; +import chart_theme_multi_color_ordered_ColorScale_1400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1400'; +import chart_theme_multi_color_ordered_ColorScale_1500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1500'; +import chart_theme_multi_color_ordered_ColorScale_1600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1600'; +import chart_theme_multi_color_ordered_ColorScale_1700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1700'; +import chart_theme_multi_color_ordered_ColorScale_1800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1800'; +import chart_theme_multi_color_ordered_ColorScale_1900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1900'; +import chart_theme_multi_color_ordered_ColorScale_2000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2000'; +import chart_theme_multi_color_ordered_ColorScale_2100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2100'; +import chart_theme_multi_color_ordered_ColorScale_2200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2200'; +import chart_theme_multi_color_ordered_ColorScale_2300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2300'; +import chart_theme_multi_color_ordered_ColorScale_2400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2400'; +import chart_theme_multi_color_ordered_ColorScale_2500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Multi-color ordered theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getMultiColorOrderedTheme = () => + ColorTheme({ + // The color order below (minus the purple color family) improves the color contrast in ordered charts; donut, pie, bar, & stack + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_100), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_200), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_300), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_400), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_500), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_600), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_700), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_800), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_900), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1000), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1100), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1200), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1300), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1400), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1500), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1600), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1700), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1800), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_1900), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_2000), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_2100), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_2200), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_2300), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_2400), + getComputedStyleValue(chart_theme_multi_color_ordered_ColorScale_2500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/multi-unordered-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/multi-unordered-theme.ts new file mode 100644 index 00000000000..6e4b9ea8103 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/multi-unordered-theme.ts @@ -0,0 +1,84 @@ +import chart_theme_multi_color_unordered_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_100'; +import chart_theme_multi_color_unordered_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_200'; +import chart_theme_multi_color_unordered_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_300'; +import chart_theme_multi_color_unordered_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_400'; +import chart_theme_multi_color_unordered_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_500'; +import chart_theme_multi_color_unordered_ColorScale_600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_600'; +import chart_theme_multi_color_unordered_ColorScale_700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_700'; +import chart_theme_multi_color_unordered_ColorScale_800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_800'; +import chart_theme_multi_color_unordered_ColorScale_900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_900'; +import chart_theme_multi_color_unordered_ColorScale_1000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1000'; +import chart_theme_multi_color_unordered_ColorScale_1100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1100'; +import chart_theme_multi_color_unordered_ColorScale_1200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1200'; +import chart_theme_multi_color_unordered_ColorScale_1300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1300'; +import chart_theme_multi_color_unordered_ColorScale_1400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1400'; +import chart_theme_multi_color_unordered_ColorScale_1500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1500'; +import chart_theme_multi_color_unordered_ColorScale_1600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1600'; +import chart_theme_multi_color_unordered_ColorScale_1700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1700'; +import chart_theme_multi_color_unordered_ColorScale_1800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1800'; +import chart_theme_multi_color_unordered_ColorScale_1900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1900'; +import chart_theme_multi_color_unordered_ColorScale_2000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2000'; +import chart_theme_multi_color_unordered_ColorScale_2100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2100'; +import chart_theme_multi_color_unordered_ColorScale_2200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2200'; +import chart_theme_multi_color_unordered_ColorScale_2300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2300'; +import chart_theme_multi_color_unordered_ColorScale_2400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2400'; +import chart_theme_multi_color_unordered_ColorScale_2500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2500'; +import chart_theme_multi_color_unordered_ColorScale_2600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2600'; +import chart_theme_multi_color_unordered_ColorScale_2700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2700'; +import chart_theme_multi_color_unordered_ColorScale_2800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2800'; +import chart_theme_multi_color_unordered_ColorScale_2900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2900'; +import chart_theme_multi_color_unordered_ColorScale_3000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3000'; +import chart_theme_multi_color_unordered_ColorScale_3100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3100'; +import chart_theme_multi_color_unordered_ColorScale_3200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3200'; +import chart_theme_multi_color_unordered_ColorScale_3300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3300'; +import chart_theme_multi_color_unordered_ColorScale_3400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3400'; +import chart_theme_multi_color_unordered_ColorScale_3500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Multi-color unordered theme -- see https://github.com/patternfly/patternfly-next/issues/1551 + * + * @private Not intended as public API and subject to change + */ +export const getMultiColorUnorderedTheme = () => + ColorTheme({ + // The color order below improves the color contrast in unordered charts; area & line + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_100), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_200), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_300), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_400), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_500), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_600), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_700), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_800), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_900), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1000), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1100), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1200), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1300), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1400), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1500), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1600), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1700), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1800), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_1900), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2000), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2100), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2200), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2300), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2400), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2500), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2600), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2700), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2800), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_2900), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_3000), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_3100), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_3200), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_3300), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_3400), + getComputedStyleValue(chart_theme_multi_color_unordered_ColorScale_3500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/orange-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/orange-theme.ts new file mode 100644 index 00000000000..af1aab797b0 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/orange-theme.ts @@ -0,0 +1,23 @@ +import chart_theme_orange_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_100'; +import chart_theme_orange_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_200'; +import chart_theme_orange_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_300'; +import chart_theme_orange_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_400'; +import chart_theme_orange_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Orange color theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getOrangeColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_orange_ColorScale_100), + getComputedStyleValue(chart_theme_orange_ColorScale_200), + getComputedStyleValue(chart_theme_orange_ColorScale_300), + getComputedStyleValue(chart_theme_orange_ColorScale_400), + getComputedStyleValue(chart_theme_orange_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/purple-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/purple-theme.ts new file mode 100644 index 00000000000..39acfb38bf4 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/purple-theme.ts @@ -0,0 +1,23 @@ +import chart_theme_purple_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_100'; +import chart_theme_purple_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_200'; +import chart_theme_purple_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_300'; +import chart_theme_purple_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_400'; +import chart_theme_purple_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Purple ordered theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getPurpleColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_purple_ColorScale_100), + getComputedStyleValue(chart_theme_purple_ColorScale_200), + getComputedStyleValue(chart_theme_purple_ColorScale_300), + getComputedStyleValue(chart_theme_purple_ColorScale_400), + getComputedStyleValue(chart_theme_purple_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/skeleton-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/skeleton-theme.ts new file mode 100644 index 00000000000..ae86b726454 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/skeleton-theme.ts @@ -0,0 +1,23 @@ +import chart_skeleton_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_100'; +import chart_skeleton_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_200'; +import chart_skeleton_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_300'; +import chart_skeleton_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_400'; +import chart_skeleton_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_500'; +import { ColorTheme } from '../skeleton-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Skeleton color theme + * + * @private Not intended as public API and subject to change + */ +export const getSkeletonColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_skeleton_ColorScale_100), + getComputedStyleValue(chart_skeleton_ColorScale_200), + getComputedStyleValue(chart_skeleton_ColorScale_300), + getComputedStyleValue(chart_skeleton_ColorScale_400), + getComputedStyleValue(chart_skeleton_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/teal-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/teal-theme.ts new file mode 100644 index 00000000000..0ad045831e3 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/teal-theme.ts @@ -0,0 +1,23 @@ +import chart_theme_teal_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_100'; +import chart_theme_teal_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_200'; +import chart_theme_teal_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_300'; +import chart_theme_teal_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_400'; +import chart_theme_teal_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Teal color theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getTealColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_teal_ColorScale_100), + getComputedStyleValue(chart_theme_teal_ColorScale_200), + getComputedStyleValue(chart_theme_teal_ColorScale_300), + getComputedStyleValue(chart_theme_teal_ColorScale_400), + getComputedStyleValue(chart_theme_teal_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/colors/yellow-theme.ts b/packages/react-charts/src/echarts/components/themes/colors/yellow-theme.ts new file mode 100644 index 00000000000..466159466ad --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/colors/yellow-theme.ts @@ -0,0 +1,23 @@ +import chart_theme_yellow_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_100'; +import chart_theme_yellow_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_200'; +import chart_theme_yellow_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_300'; +import chart_theme_yellow_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_400'; +import chart_theme_yellow_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_500'; +import { ColorTheme } from '../color-theme'; +import { getComputedStyleValue } from '../../utils/styles'; + +/** + * Yellow color theme -- see https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit + * + * @private Not intended as public API and subject to change + */ +export const getYellowColorTheme = () => + ColorTheme({ + COLOR_SCALE: [ + getComputedStyleValue(chart_theme_yellow_ColorScale_100), + getComputedStyleValue(chart_theme_yellow_ColorScale_200), + getComputedStyleValue(chart_theme_yellow_ColorScale_300), + getComputedStyleValue(chart_theme_yellow_ColorScale_400), + getComputedStyleValue(chart_theme_yellow_ColorScale_500) + ] + }); diff --git a/packages/react-charts/src/echarts/components/themes/skeleton-theme.ts b/packages/react-charts/src/echarts/components/themes/skeleton-theme.ts new file mode 100644 index 00000000000..76adeea2815 --- /dev/null +++ b/packages/react-charts/src/echarts/components/themes/skeleton-theme.ts @@ -0,0 +1,212 @@ +import chart_echarts_BackgroundColor from '@patternfly/react-tokens/dist/esm/chart_echarts_BackgroundColor'; +import chart_echarts_global_axis_axis_line_item_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_axis_line_item_style_Color'; +import chart_echarts_global_axis_axis_tick_item_style_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_global_axis_axis_tick_item_style_Color'; +import chart_echarts_skeleton_label_Color from '@patternfly/react-tokens/dist/esm/chart_echarts_skeleton_label_Color'; + +import { ThemeDefinition } from '../themes/Theme'; +import { getComputedStyleValue } from '../utils/styles'; + +interface ColorThemeInterface { + COLOR_SCALE: string[]; +} + +/** + * ECharts skeleton color theme + * + * @private Not intended as public API and subject to change + */ +export const ColorTheme = (props: ColorThemeInterface): ThemeDefinition => { + const { COLOR_SCALE } = props; + + const labelProps = { + backgroundColor: COLOR_SCALE[0], + color: getComputedStyleValue(chart_echarts_skeleton_label_Color) + }; + + const axisProps = { + axisLabel: { ...labelProps }, + axisLine: { + lineStyle: { + color: getComputedStyleValue(chart_echarts_global_axis_axis_line_item_style_Color) + } + }, + axisTick: { + lineStyle: { + color: getComputedStyleValue(chart_echarts_global_axis_axis_tick_item_style_Color) + } + }, + splitArea: { + areaStyle: { + color: COLOR_SCALE + } + }, + splitLine: { + lineStyle: { + color: [COLOR_SCALE[0]] + } + } + }; + + return { + color: COLOR_SCALE, + backgroundColor: getComputedStyleValue(chart_echarts_BackgroundColor), // See https://echarts.apache.org/en/option.html#backgroundColor + bar: { + itemStyle: { + barBorderColor: COLOR_SCALE[0] + } + }, + boxplot: { + itemStyle: { + borderColor: COLOR_SCALE[0] + } + }, + candlestick: { + itemStyle: { + borderColor: COLOR_SCALE[0], + borderColor0: COLOR_SCALE[1], + color: COLOR_SCALE[0], + color0: COLOR_SCALE[1] + } + }, + categoryAxis: { ...axisProps }, + dataZoom: {}, + funnel: { + itemStyle: { + borderColor: COLOR_SCALE[0] + } + }, + gauge: { + itemStyle: { + borderColor: COLOR_SCALE[0] + } + }, + geo: { + emphasis: { + itemStyle: { + areaColor: COLOR_SCALE[0], + borderColor: COLOR_SCALE[0] + }, + label: { ...labelProps } + }, + itemStyle: { + areaColor: COLOR_SCALE[0], + borderColor: COLOR_SCALE[0] + }, + label: { ...labelProps } + }, + graph: { + color: COLOR_SCALE, + itemStyle: { + borderColor: COLOR_SCALE[0] + }, + label: { ...labelProps }, + lineStyle: { + color: COLOR_SCALE[0] + } + }, + label: { ...labelProps }, + legend: { + textStyle: { ...labelProps } + }, + line: {}, + logAxis: { ...axisProps }, + map: { + emphasis: { + itemStyle: { + areaColor: COLOR_SCALE[0], + borderColor: COLOR_SCALE[0] + }, + label: { ...labelProps } + }, + itemStyle: { + areaColor: COLOR_SCALE[0], + borderColor: COLOR_SCALE[0] + }, + label: { ...labelProps } + }, + markPoint: { + emphasis: { + label: { ...labelProps } + }, + label: { ...labelProps } + }, + parallel: { + itemStyle: { + borderColor: COLOR_SCALE[0] + } + }, + pie: { + itemStyle: { + borderColor: COLOR_SCALE[0] + } + }, + radar: {}, + sankey: { + itemStyle: { + borderColor: COLOR_SCALE[0] + } + }, + scatter: { + itemStyle: { + borderColor: COLOR_SCALE[0] + } + }, + textStyle: {}, + timeAxis: { ...axisProps }, + timeline: { + emphasis: { + controlStyle: { + color: COLOR_SCALE[0], + borderColor: COLOR_SCALE[0] + }, + itemStyle: { + color: COLOR_SCALE[0] + }, + label: { ...labelProps } + }, + checkpointStyle: { + color: COLOR_SCALE[0], + borderColor: COLOR_SCALE[0] + }, + controlStyle: { + color: COLOR_SCALE[0], + borderColor: COLOR_SCALE[0] + }, + itemStyle: { + color: COLOR_SCALE[0] + }, + label: { ...labelProps }, + lineStyle: { + color: COLOR_SCALE[0] + } + }, + title: { + subtextStyle: { ...labelProps }, + textStyle: { ...labelProps } + }, + toolbox: { + emphasis: { + iconStyle: { + borderColor: COLOR_SCALE[0] + } + }, + iconStyle: { + borderColor: COLOR_SCALE[0] + } + }, + tooltip: { + axisPointer: { + crossStyle: { + color: COLOR_SCALE[0] + }, + lineStyle: { + color: COLOR_SCALE[0] + } + } + }, + valueAxis: { ...axisProps }, + visualMap: { + color: COLOR_SCALE + } + }; +}; diff --git a/packages/react-charts/src/echarts/components/utils/observe.ts b/packages/react-charts/src/echarts/components/utils/observe.ts new file mode 100644 index 00000000000..293776f91a8 --- /dev/null +++ b/packages/react-charts/src/echarts/components/utils/observe.ts @@ -0,0 +1,37 @@ +/** + * Mutation Observer Helper function -- see developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe + * + * @param {string} selector The DOM selector to watch + * @param {object} opt MutationObserver options + * @param {function} cb Pass Mutation object to a callback function + * @private Not intended as public API and subject to change + */ +export const observe = (selector: any, opt: any, cb: any) => { + let unobserve: any; + + if (selector) { + const Obs = new MutationObserver((m) => [...m].forEach(cb)); + document.querySelectorAll(selector).forEach((el) => Obs.observe(el, opt)); + unobserve = () => Obs.disconnect(); + } + return () => { + if (unobserve) { + unobserve(); + } + }; +}; + +// See https://stackoverflow.com/questions/17134823/detect-element-style-changes-with-javascript +export const getMutationObserver = (nodeSelector: string, cb: any) => + observe( + nodeSelector, + { + attributesList: ['style'], // Only the "style" attribute + attributeOldValue: true // Report also the oldValue + }, + (m: any) => { + if (cb) { + cb(m); + } + } + ); diff --git a/packages/react-charts/src/echarts/components/utils/styles.ts b/packages/react-charts/src/echarts/components/utils/styles.ts new file mode 100644 index 00000000000..862be8950dd --- /dev/null +++ b/packages/react-charts/src/echarts/components/utils/styles.ts @@ -0,0 +1,50 @@ +/** + * Copied from exenv + * + * @private Not intended as public API and subject to change + */ +export const canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); + +/** + * Returns the class name that will be applied to the outermost div rendered by the chart's container + * + * @private Not intended as public API and subject to change + */ +export const getClassName = (className: string) => { + let cleanClassName; + + // Cleanup class name + if (className) { + cleanClassName = className + .replace(/pf-v6-c-chart/g, '') + .replace(/pf-c-chart/g, '') + .replace(/\s+/g, ' ') + .trim(); + } + return cleanClassName?.length ? `pf-v6-c-chart ${cleanClassName}` : 'pf-v6-c-chart'; +}; + +/** + * Get computed style value -- see https://github.com/apache/echarts/issues/19743 + * + * Note that Victory uses the style property to apply CSS variables. However, ECharts' LineChart uses `fill` and + * `stroke` attributes, which doesn't work with CSS variables. In addition, using CSS variables with Sankey + * causes sever flashing during mouse hover. Therefore, we will obtain the CSS computed value from the DOM. + * + * @public + * @beta + */ +export const getComputedStyleValue = (token: { name: string; value: string | number; var: string }) => { + let result: any; + + if (canUseDOM) { + result = window.getComputedStyle(document.body)?.getPropertyValue(token.name); + + if (result === '') { + result = undefined; + } else if (!isNaN(result) || result === 'true' || result === 'false') { + result = JSON.parse(result); + } + } + return result !== undefined ? result : token.value; +}; diff --git a/packages/react-charts/src/echarts/components/utils/symbol.tsx b/packages/react-charts/src/echarts/components/utils/symbol.tsx new file mode 100644 index 00000000000..1c1bc4032fa --- /dev/null +++ b/packages/react-charts/src/echarts/components/utils/symbol.tsx @@ -0,0 +1,165 @@ +import { getComputedStyleValue } from './styles'; + +import chart_echarts_BackgroundColor from '@patternfly/react-tokens/dist/esm/chart_echarts_BackgroundColor'; + +const enum SymbolType { + arrow = 'arrow', + circle = 'circle', + diamond = 'diamond', + emptyArrow = 'emptyArrow', + emptyCircle = 'emptyCircle', + emptyDiamond = 'emptyDiamond', + emptyPin = 'emptyPin', + emptyRect = 'emptyRect', + emptyRoundRect = 'emptyRoundRect', + emptySquare = 'emptySquare', + emptyTriangle = 'emptyTriangle', + pin = 'pin', + rect = 'rect', + roundRect = 'roundRect', + square = 'square', + triangle = 'triangle' +} + +// ECharts icon types -- see https://svg-path.com/ +const symbols = { + arrow: 'M12.5 7L19.9667 18.2L12.5 15.4L5.0333 18.2L12.5 7Z', + circle: 'M18.1 7A5.6 5.6 0 1 1 18.1 6.9994Z', + diamond: 'M12.5 1.4L18.1 7L12.5 12.6L6.9 7Z', + emptyArrow: 'M12.5 7L19.9667 18.2L12.5 15.4L5.0333 18.2L12.5 7Z', + emptyCircle: 'M18.1 7A5.6 5.6 0 1 1 18.1 6.9994Z', + emptyDiamond: 'M12.5 1.4L18.1 7L12.5 12.6L6.9 7Z', + emptyPin: + 'M9.4642 2.04A3.36 3.36 0 1 1 15.5358 2.04C14.6718 3.8615 12.5 4.648 12.5 7C12.5 4.648 10.3282 3.8615 9.4642 2.04Z', + emptyRect: 'M6.9,1.4 l14.2,0 l0,11.2 l-14.2,0 Z', + emptyRoundRect: + 'M9.7,1.4 L18.3,1.4 A2.8,2.8,0,0,1,21.1,4.2 L21.1,9.8 A2.8,2.8,0,0,1,18.3,12.6 L9.7,12.6 A2.8,2.8,0,0,1,6.9,9.8 L6.9,4.2 A2.8,2.8,0,0,1,9.7,1.4 Z', + emptySquare: 'M6.9 1.4l11.2 0l0 11.2l-11.2 0Z', + emptyTriangle: 'M12.5 1.4L18.1 12.5L12.5 12.5L6.9 12.5Z', + pin: 'M9.4642 2.04A3.36 3.36 0 1 1 15.5358 2.04C14.6718 3.8615 12.5 4.648 12.5 7C12.5 4.648 10.3282 3.8615 9.4642 2.04Z', + rect: 'M6.9,1.4 l18.2,0 l0,11.2 l-18.2,0 Z', + roundRect: + 'M9.7,1.4 L22.3,1.4 A2.8,2.8,0,0,1,25.1,4.2 L25.1,9.8 A2.8,2.8,0,0,1,22.3,12.6 L9.7,12.6 A2.8,2.8,0,0,1,6.9,9.8 L6.9,4.2 A2.8,2.8,0,0,1,9.7,1.4 Z', + square: 'M6.9 1.4l11.2 0l0 11.2l-11.2 0Z', + triangle: 'M12.5 1.4L18.1 12.5L12.5 12.5L6.9 12.5Z' +}; + +/** + * Returns marker -- see https://github.com/apache/echarts/issues/19826 + * + * @param serie + * @param symbol + * @param color + * @private Not intended as public API and subject to change + */ +export const getMarker = (serie: any, symbol: string, color: string = '') => { + const size = 18; + let path; + let pathStyle = `fill:${color};`; + const svgStyle = 'vertical-align: middle;'; + + let transform; + + // Set marker type + switch (symbol) { + case SymbolType.arrow: + case SymbolType.circle: + case SymbolType.diamond: + case SymbolType.emptyArrow: + case SymbolType.emptyCircle: + case SymbolType.emptyDiamond: + case SymbolType.emptyPin: + case SymbolType.emptyRect: + case SymbolType.emptyRoundRect: + case SymbolType.emptySquare: + case SymbolType.emptyTriangle: + case SymbolType.pin: + case SymbolType.rect: + case SymbolType.roundRect: + case SymbolType.square: + case SymbolType.triangle: + path = symbols[symbol]; + break; + default: + path = symbols.square; + break; + } + + // Set path style for EChart symbols + switch (symbol) { + case SymbolType.emptyArrow: + case SymbolType.emptyCircle: + case SymbolType.emptyDiamond: + case SymbolType.emptyPin: + case SymbolType.emptyRect: + case SymbolType.emptyRoundRect: + case SymbolType.emptySquare: + case SymbolType.emptyTriangle: + pathStyle = `fill:${getComputedStyleValue(chart_echarts_BackgroundColor)}; stroke:${color}; stroke-width:2`; + break; + default: + pathStyle = `fill:${color}; margin-left:-50px;`; + } + + // Set SVG style for EChart symbols + switch (symbol) { + case SymbolType.arrow: + case SymbolType.emptyArrow: + transform = `translate(-5 -5)`; + break; + case SymbolType.emptyDiamond: + transform = `translate(-5 5)`; + break; + case SymbolType.emptyRect: + case SymbolType.emptyRoundRect: + transform = `translate(-5 0)`; + break; + case SymbolType.pin: + transform = `translate(-5 5)`; + break; + case SymbolType.rect: + transform = `translate(-7 0)`; + break; + case SymbolType.roundRect: + transform = `translate(-7 0)`; + break; + default: + transform = `translate(-5 0)`; + break; + } + + const marker = ``; + const svg = `${marker}`; + + return svg; +}; + +/** + * Returns default symbol + * + * @param series + * @param seriesIndex + * @param echart + * @private Not intended as public API and subject to change + */ +export const getSymbol = (series: any, seriesIndex: number, echart: any) => { + const ase = echart?.getModel().findComponents({ mainType: 'series' }); + const data = ase[seriesIndex].getData(); + const symbol = data?.getVisual('symbol')?.replace(/"/g, ''); + + if (!symbol) { + const serie = series[seriesIndex]; + if (serie?.symbol) { + return serie?.symbol; + } + switch (serie?.type) { + case 'bar': + return SymbolType.rect; + case 'line': + return SymbolType.square; + default: + break; + } + } + return symbol; +}; diff --git a/packages/react-charts/src/echarts/components/utils/theme.ts b/packages/react-charts/src/echarts/components/utils/theme.ts new file mode 100644 index 00000000000..f4f9c996c6a --- /dev/null +++ b/packages/react-charts/src/echarts/components/utils/theme.ts @@ -0,0 +1,68 @@ +import cloneDeep from 'lodash/cloneDeep'; +import merge from 'lodash/merge'; +import { ThemeColor } from '../themes/ThemeColor'; +import { ThemeDefinition } from '../themes/Theme'; +import { BaseTheme } from '../themes/base-theme'; +import { getBlueColorTheme } from '../themes/colors/blue-theme'; +import { getTealColorTheme } from '../themes/colors/teal-theme'; +import { getYellowColorTheme } from '../themes/colors/yellow-theme'; +import { getGrayColorTheme } from '../themes/colors/gray-theme'; +import { getGreenColorTheme } from '../themes/colors/green-theme'; +import { getSkeletonColorTheme } from '../themes/colors/skeleton-theme'; +import { getMultiColorOrderedTheme } from '../themes/colors/multi-ordered-theme'; +import { getMultiColorUnorderedTheme } from '../themes/colors/multi-unordered-theme'; +import { getOrangeColorTheme } from '../themes/colors/orange-theme'; +import { getPurpleColorTheme } from '../themes/colors/purple-theme'; + +/** + * Apply custom properties to base and color themes + * + * @param themeColor The theme color to merge with custom theme + * @param customTheme The custom theme to merge + * @public + * @beta + */ +export const getCustomTheme = (themeColor: string, customTheme: ThemeDefinition): ThemeDefinition => + merge(getTheme(themeColor), customTheme); + +/** + * Returns base theme for given color + * @public + * @beta + */ +export const getTheme = (themeColor: string): ThemeDefinition => { + const baseTheme = cloneDeep(BaseTheme()); + return merge(baseTheme, getThemeColors(themeColor)); +}; + +/** + * Returns computed theme colors + * @private Not intended as public API and subject to change + */ +const getThemeColors = (themeColor: string) => { + switch (themeColor) { + case ThemeColor.blue: + return getBlueColorTheme(); + case ThemeColor.teal: + return getTealColorTheme(); + case ThemeColor.yellow: + return getYellowColorTheme(); + case ThemeColor.gray: + return getGrayColorTheme(); + case ThemeColor.green: + return getGreenColorTheme(); + case ThemeColor.multi: + case ThemeColor.multiOrdered: + return getMultiColorOrderedTheme(); + case ThemeColor.multiUnordered: + return getMultiColorUnorderedTheme(); + case ThemeColor.orange: + return getOrangeColorTheme(); + case ThemeColor.purple: + return getPurpleColorTheme(); + case ThemeColor.skeleton: + return getSkeletonColorTheme(); + default: + return getBlueColorTheme(); + } +}; diff --git a/packages/react-charts/src/echarts/components/utils/tooltip.tsx b/packages/react-charts/src/echarts/components/utils/tooltip.tsx new file mode 100644 index 00000000000..6c3558a0c3d --- /dev/null +++ b/packages/react-charts/src/echarts/components/utils/tooltip.tsx @@ -0,0 +1,102 @@ +import defaultsDeep from 'lodash/defaultsDeep'; + +import { ChartsOptionProps } from '../Charts'; +import { getMarker, getSymbol } from './symbol'; + +/** + * Returns a custom legend tooltip for Line charts + * + * @param series + * @param option + * @param echart + * @private Not intended as public API and subject to change + */ +export const getLegendTooltip = (series: any[], option: ChartsOptionProps, echart: any) => { + const tooltip = option?.tooltip as any; + const valueFormatter = tooltip?.valueFormatter ? tooltip.valueFormatter : (value: number | string) => value; + + const defaults = { + confine: true, + formatter: (params: any) => { + let result = ''; + params?.map((param, index) => { + if (index === 0) { + result += `

    ${param.name}

    `; + } + const symbol = getSymbol(series, param.seriesIndex, echart); + const marker = getMarker(series[param.seriesIndex], symbol, param.color); + const formattedValue = valueFormatter(param.value, param.dataIndex); + const seriesName = `${param.seriesName}`; + const value = `${formattedValue}`; + + result += `

    ${marker}${seriesName}${value}

    `; + }); + return result; + }, + trigger: 'axis' + }; + return defaultsDeep(tooltip, defaults); +}; + +/** + * Returns source and target colors from given series + * + * @param series + * @param formatterParams + * @private Not intended as public API and subject to change + */ +const getItemColor = (series: any[], formatterParams: any) => { + const serie = series[formatterParams.seriesIndex]; + const sourceData = serie?.data.find((datum: any) => datum.name === formatterParams.data?.source); + const targetData = serie?.data.find((datum: any) => datum.name === formatterParams.data?.target); + const sourceColor = sourceData?.itemStyle?.color; + const targetColor = targetData?.itemStyle?.color; + return { sourceColor, targetColor }; +}; + +/** + * Returns a custom legend tooltip for Sankey chart + * + * @param series + * @param option + * @private Not intended as public API and subject to change + */ +export const getSankeyTooltip = (series: any[], option: ChartsOptionProps) => { + const symbolSize = '10px'; + const tooltip = option?.tooltip as any; + const sourceLabel = tooltip?.sourceLabel ? tooltip.sourceLabel : ''; + const destinationLabel = tooltip?.destinationLabel ? tooltip.destinationLabel : ''; + const valueFormatter = tooltip?.valueFormatter ? tooltip.valueFormatter : (value: number | string) => value; + + const defaults = { + confine: true, + formatter: (params: any) => { + let result; + if (params?.data?.source && params?.data?.target) { + const { sourceColor, targetColor } = getItemColor(series, params); + result = ` +

    ${sourceLabel}

    +
    + ${params.data.source} +

    ${destinationLabel}

    +

    +

    + ${params.data.target} + + ${valueFormatter(params.value, params.dataIndex)} + +

    + `; + } else { + result = ` +
    + ${params.name} ${valueFormatter(params.value, params.dataIndex)} + `; + } + return result.replace(/\s\s+/g, ' '); + }, + trigger: 'item', + triggerOn: 'mousemove' + }; + return defaultsDeep(tooltip, defaults); +}; diff --git a/packages/react-catalog-view-extension/src/index.ts b/packages/react-charts/src/echarts/index.ts similarity index 100% rename from packages/react-catalog-view-extension/src/index.ts rename to packages/react-charts/src/echarts/index.ts diff --git a/packages/react-charts/src/echarts/typings/echarts.d.ts b/packages/react-charts/src/echarts/typings/echarts.d.ts new file mode 100644 index 00000000000..497834cab88 --- /dev/null +++ b/packages/react-charts/src/echarts/typings/echarts.d.ts @@ -0,0 +1,7 @@ +import * as echarts from 'echarts/types/dist/core'; + +declare module 'echarts' { + export const registerTheme: echarts.registerTheme; + export const init: echarts.init; + export type ECharts = any; +} diff --git a/packages/react-charts/src/components/Chart/Chart.test.tsx b/packages/react-charts/src/victory/components/Chart/Chart.test.tsx similarity index 75% rename from packages/react-charts/src/components/Chart/Chart.test.tsx rename to packages/react-charts/src/victory/components/Chart/Chart.test.tsx index 3354f9e0279..e7ec1c59d35 100644 --- a/packages/react-charts/src/components/Chart/Chart.test.tsx +++ b/packages/react-charts/src/victory/components/Chart/Chart.test.tsx @@ -1,18 +1,17 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { Chart } from './Chart'; -import { ChartGroup } from '../ChartGroup'; -import { ChartLine } from '../ChartLine'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartLine } from '../ChartLine/ChartLine'; Object.values([true, false]).forEach(() => { test('Chart', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); }); test('renders axis and component children', () => { - const view = shallow( + const { asFragment } = render( { ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-charts/src/victory/components/Chart/Chart.tsx b/packages/react-charts/src/victory/components/Chart/Chart.tsx new file mode 100644 index 00000000000..41790cf2f91 --- /dev/null +++ b/packages/react-charts/src/victory/components/Chart/Chart.tsx @@ -0,0 +1,664 @@ +import { Children, cloneElement, isValidElement, useEffect } from 'react'; +import hoistNonReactStatics from 'hoist-non-react-statics'; + +import chart_legend_Margin from '@patternfly/react-tokens/dist/esm/chart_legend_Margin'; + +import { + AnimatePropTypeInterface, + D3Scale, + DomainPropType, + DomainPaddingPropType, + EventCallbackInterface, + EventPropTypeInterface, + PaddingProps, + RangePropType, + ScalePropType, + StringOrNumberOrCallback, + StringOrNumberOrList, + VictoryStyleInterface, + VictoryStyleObject +} from 'victory-core'; +import { AxesType, VictoryChart, VictoryChartProps } from 'victory-chart'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLegend } from '../ChartLegend/ChartLegend'; +import { ChartCommonStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getClassName } from '../ChartUtils/chart-helpers'; +import { getLabelTextSize } from '../ChartUtils/chart-label'; +import { getComputedLegend, getLegendItemsExtraHeight, getLegendMaxTextWidth } from '../ChartUtils/chart-legend'; +import { getPaddingForSide } from '../ChartUtils/chart-padding'; +import { getPatternDefs, mergePatternData, useDefaultPatternProps } from '../ChartUtils/chart-patterns'; +import { getChartTheme } from '../ChartUtils/chart-theme-types'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartPoint } from '../ChartPoint/ChartPoint'; +import { ChartThemeColor } from '../ChartTheme/ChartThemeColor'; + +/** + * Chart is a wrapper component that reconciles the domain for all its children, controls the layout of the chart, + * and coordinates animations and shared events. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-chart/src/victory-chart.tsx + */ +export interface ChartProps extends VictoryChartProps { + /** + * The animate prop specifies props for VictoryAnimation to use. + * The animate prop should also be used to specify enter and exit + * transition configurations with the `onExit` and `onEnter` namespaces respectively. + * + * @propType boolean | object + * @example {duration: 500, onExit: () => {}, onEnter: {duration: 500, before: () => ({y: 0})})} + */ + animate?: boolean | AnimatePropTypeInterface; + /** + * The ariaDesc prop specifies the description of the chart/SVG to assist with + * accessibility for screen readers. + * + * Note: Overridden by the desc prop of containerComponent + */ + ariaDesc?: string; + /** + * The ariaTitle prop specifies the title to be applied to the SVG to assist + * accessibility for screen readers. + * + * Note: Overridden by the title prop of containerComponent + */ + ariaTitle?: string; + /** + * The backgroundComponent prop takes a component instance which will be responsible for rendering a background if the + * Chart's style component includes background styles. The new element created from the passed backgroundComponent + * will be provided with the following properties calculated by Chart: height, polar, scale, style, x, y, width. + * All of these props on Background should take precedence over what VictoryChart is trying to set. + */ + backgroundComponent?: React.ReactElement; + /** + * The children to render with the chart + */ + children?: React.ReactNode | React.ReactNode[]; + /** + * The containerComponent prop takes an entire component which will be used to + * create a container element for standalone charts. + * The new element created from the passed containerComponent wil be provided with + * these props from ChartArea: height, width, children + * (the chart itself) and style. Props that are not provided by the + * child chart component include title and desc, both of which + * are intended to add accessibility to Victory components. The more descriptive these props + * are, the more accessible your data will be for people using screen readers. + * Any of these props may be overridden by passing in props to the supplied component, + * or modified or ignored within the custom component itself. If a dataComponent is + * not provided, ChartArea will use the default ChartContainer component. + * + * @example + */ + containerComponent?: React.ReactElement; + /** + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + defaultAxes?: AxesType; + /** + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + defaultPolarAxes?: AxesType; + /** + * The domain prop describes the range of values your chart will include. This prop can be + * given as a array of the minimum and maximum expected values for your chart, + * or as an object that specifies separate arrays for x and y. + * If this prop is not provided, a domain will be calculated from data, or other + * available information. + * + * @propType number[] | { x: number[], y: number[] } + * @example [low, high], { x: [low, high], y: [low, high] } + * + * [-1, 1], {x: [0, 100], y: [0, 1]} + */ + domain?: DomainPropType; + /** + * The domainPadding prop specifies a number of pixels of padding to add to the + * beginning and end of a domain. This prop is useful for explicitly spacing ticks farther + * from the origin to prevent crowding. This prop should be given as an object with + * numbers specified for x and y. + * + * @propType number | number[] | { x: number[], y: number[] } + * @example [left, right], { x: [left, right], y: [bottom, top] } + * + * {x: [10, -10], y: 5} + */ + domainPadding?: DomainPaddingPropType; + /** + * The endAngle props defines the overall end angle of a polar chart in degrees. This prop is used in conjunction with + * startAngle to create polar chart that spans only a segment of a circle, or to change overall rotation of the chart. + * This prop should be given as a number of degrees. Degrees are defined as starting at the 3 o'clock position, and + * proceeding counterclockwise. + */ + endAngle?: number; + /** + * Similar to data accessor props `x` and `y`, this prop may be used to functionally + * assign eventKeys to data + * + * @propType number | string | Function + */ + eventKey?: StringOrNumberOrCallback; + /** + * The event prop takes an array of event objects. Event objects are composed of + * a target, an eventKey, and eventHandlers. Targets may be any valid style namespace + * for a given component, so "data" and "labels" are all valid targets for ChartPie + * events. The eventKey may optionally be used to select a single element by index rather than + * an entire set. The eventHandlers object should be given as an object whose keys are standard + * event names (i.e. onClick) and whose values are event callbacks. The return value + * of an event handler is used to modify elements. The return value should be given + * as an object or an array of objects with optional target and eventKey keys, + * and a mutation key whose value is a function. The target and eventKey keys + * will default to those corresponding to the element the event handler was attached to. + * The mutation function will be called with the calculated props for the individual selected + * element (i.e. a single bar), and the object returned from the mutation function + * will override the props of the selected element via object assignment. + * + * @propType object[] + * @example + * events={[ + * { + * target: "data", + * eventKey: 1, + * eventHandlers: { + * onClick: () => { + * return [ + * { + * eventKey: 2, + * mutation: (props) => { + * return {style: merge({}, props.style, {fill: "orange"})}; + * } + * }, { + * eventKey: 2, + * target: "labels", + * mutation: () => { + * return {text: "hey"}; + * } + * } + * ]; + * } + * } + * } + * ]} + */ + events?: EventPropTypeInterface[]; + /** + * Chart uses the standard externalEventMutations prop. + * + * @propType object[] + */ + externalEventMutations?: EventCallbackInterface[]; + /** + * The groupComponent prop takes an entire component which will be used to + * create group elements for use within container elements. This prop defaults + * to a tag on web, and a react-native-svg tag on mobile + */ + groupComponent?: React.ReactElement; + /** + * The hasPatterns prop is an optional prop that indicates whether a pattern is shown for a chart. + * SVG patterns are dynamically generated (unique to each chart) in order to apply colors from the selected + * color theme or custom color scale. Those generated patterns are applied in a specific order (via a URL), similar + * to the color theme ordering defined by PatternFly. If the multi-color theme was in use; for example, colorized + * patterns would be displayed in that same order. Create custom patterns via the patternScale prop. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example hasPatterns={ true } + * @example hasPatterns={[ true, true, false ]} + */ + hasPatterns?: boolean | boolean[]; + /** + * Specifies the height the svg viewBox of the chart container. This value should be given as a + * number of pixels. + * + * Because Victory renders responsive containers, the width and height props do not determine the width and + * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of + * pixels will depend on the size of the container the chart is rendered into. Typically, the parent container is set + * to the same width in order to maintain the aspect ratio. + */ + height?: number; + /** + * The horizontal prop determines whether data will be plotted horizontally. When this prop is set to true, the + * independent variable will be plotted on the y axis and the dependent variable will be plotted on the x axis. + */ + horizontal?: boolean; + /** + * When the innerRadius prop is set, polar charts will be hollow rather than circular. + * + * @propType number | Function + */ + innerRadius?: number; + /** + * Allows legend items to wrap onto the next line if the chart is not wide enough. + * + * Note that the chart's SVG height and width are 100% by default, so it can be responsive itself. However, if you + * define the height and width of the chart's parent container, you must accommodate for extra legend height due to + * legend items wrapping onto the next line. When the height of the chart's parent container is too small, some legend + * items may not be visible. + * + * Alternatively, a callback function may be provided, which will be called after the legend's itemsPerRow property + * has been calculated. The value provided can be used to increase the chart's parent container height as legend + * items wrap onto the next line. If no adjustment is necessary, the value will be zero. + * + * Note: This is overridden by the legendItemsPerRow property + */ + legendAllowWrap?: boolean | ((extraHeight: number) => void); + /** + * The legend component to render with chart. + * + * Note: Use legendData so the legend width can be calculated and positioned properly. + * Default legend properties may be applied + */ + legendComponent?: React.ReactElement; + /** + * Specify data via the data prop. ChartLegend expects data as an + * array of objects with name (required), symbol, and labels properties. + * The data prop must be given as an array. + * + * @example legendData={[{ name: `GBps capacity - 45%` }, { name: 'Unused' }]} + */ + legendData?: { + name?: string; + symbol?: { + fill?: string; + type?: string; + }; + }[]; + /** + * The orientation prop takes a string that defines whether legend data + * are displayed in a row or column. When orientation is "horizontal", + * legend items will be displayed in a single row. When orientation is + * "vertical", legend items will be displayed in a single column. Line + * and text-wrapping is not currently supported, so "vertical" + * orientation is both the default setting and recommended for + * displaying many series of data. + */ + legendOrientation?: 'horizontal' | 'vertical'; + /** + * The legend position relation to the chart. Valid values are 'bottom', 'bottom-left', and 'right' + * + * Note: When adding a legend, padding may need to be adjusted in order to accommodate the extra legend. In some + * cases, the legend may not be visible until enough padding is applied. + */ + legendPosition?: 'bottom' | 'bottom-left' | 'right'; + /** + * Text direction of the legend labels. + */ + legendDirection?: 'ltr' | 'rtl'; + /** + * The maxDomain prop defines a maximum domain value for a chart. This prop is useful in situations where the maximum + * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain + * prop is set in addition to maximumDomain, domain will be used. + * + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to + * the y axis. + * + * @example + * + * maxDomain={0} + * maxDomain={{ y: 0 }} + */ + maxDomain?: number | { x?: number; y?: number }; + /** + * The minDomain prop defines a minimum domain value for a chart. This prop is useful in situations where the minimum + * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain + * prop is set in addition to minimumDomain, domain will be used. + * + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to + * the y axis. + * + * @example + * + * minDomain={0} + * minDomain={{ y: 0 }} + */ + minDomain?: number | { x?: number; y?: number }; + /** + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. + */ + name?: string; + /** + * The padding props specifies the amount of padding in number of pixels between + * the edge of the chart and any rendered child components. This prop can be given + * as a number or as an object with padding specified for top, bottom, left + * and right. + * + * @propType number | { top: number, bottom: number, left: number, right: number } + */ + padding?: PaddingProps; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; + /** + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + prependDefaultAxes?: boolean; + /** + * Victory components can pass a boolean polar prop to specify whether a label is part of a polar chart. + */ + polar?: boolean; + /** + * The range prop describes the dimensions over which data may be plotted. For cartesian coordinate systems, this + * corresponds to minimum and maximum svg coordinates in the x and y dimension. In polar coordinate systems this + * corresponds to a range of angles and radii. When this value is not given it will be calculated from the width, + * height, and padding, or from the startAngle and endAngle in the case of polar charts. All components in a given + * chart must share the same range, so setting this prop on children nested within Chart, ChartStack, or + * ChartGroup will have no effect. This prop is usually not set manually. + * + * @propType number[] | { x: number[], y: number[] } + * @example [low, high] | { x: [low, high], y: [low, high] } + * + * Cartesian: range={{ x: [50, 250], y: [50, 250] }} + * Polar: range={{ x: [0, 360], y: [0, 250] }} + */ + range?: RangePropType; + /** + * The scale prop determines which scales your chart should use. This prop can be + * given as a string specifying a supported scale ("linear", "time", "log", "sqrt"), + * as a d3 scale function, or as an object with scales specified for x and y + * + * @propType string | { x: string, y: string } + * @example d3Scale.time(), {x: "linear", y: "log"} + */ + scale?: + | ScalePropType + | D3Scale + | { + x?: ScalePropType | D3Scale; + y?: ScalePropType | D3Scale; + }; + /** + * The sharedEvents prop is used internally to coordinate events between components. + * + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + sharedEvents?: { events: any[]; getEventState: Function }; + /** + * Convenience prop to hide both x and y axis, which are shown by default. Alternatively, the axis can be hidden via + * chart styles. + */ + showAxis?: boolean; + /** + * By default domainPadding is coerced to existing quadrants. This means that if a given domain only includes positive + * values, no amount of padding applied by domainPadding will result in a domain with negative values. This is the + * desired behavior in most cases. For users that need to apply padding without regard to quadrant, the + * singleQuadrantDomainPadding prop may be used. This prop may be given as a boolean or an object with boolean values + * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied + * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. + * + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable + * will corresponds to the y axis. + * + * @example + * + * singleQuadrantDomainPadding={false} + * singleQuadrantDomainPadding={{ x: false }} + */ + singleQuadrantDomainPadding?: boolean | { x?: boolean; y?: boolean }; + /** + * The standalone prop determines whether the component will render a standalone svg + * or a tag that will be included in an external svg. Set standalone to false to + * compose Chart with other components within an enclosing tag. + */ + standalone?: boolean; + /** + * The startAngle props defines the overall start angle of a polar chart in degrees. This prop is used in conjunction + * with endAngle to create polar chart that spans only a segment of a circle, or to change overall rotation of the + * chart. This prop should be given as a number of degrees. Degrees are defined as starting at the 3 o'clock position, + * and proceeding counterclockwise. + */ + startAngle?: number; + /** + * The style prop defines the style of the component. The style prop should be given as an object with styles defined + * for data, labels and parent. Any valid svg styles are supported, but width, height, and padding should be specified + * via props as they determine relative layout for components in Chart. + * + * @propType { parent: object, background: object } + * @propType { parent: object, background: object } + */ + style?: Pick & { background?: VictoryStyleObject }; + /** + * The theme prop specifies a theme to use for determining styles and layout properties for a component. Any styles or + * props defined in theme may be overwritten by props specified on the component instance. + * + * @propType object + */ + theme?: ChartThemeDefinition; + /** + * Specifies the theme color. Valid values are 'blue', 'green', 'multi', etc. + * + * Note: Not compatible with theme prop + * + * @example themeColor={ChartThemeColor.blue} + */ + themeColor?: string; + /** + * Specifies the width of the svg viewBox of the chart container. This value should be given as a + * number of pixels. + * + * Because Victory renders responsive containers, the width and height props do not determine the width and + * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of + * pixels will depend on the size of the container the chart is rendered into. Typically, the parent container is set + * to the same width in order to maintain the aspect ratio. + */ + width?: number; +} + +export const Chart: React.FunctionComponent = ({ + ariaDesc, + ariaTitle, + children, + colorScale, + hasPatterns, + legendAllowWrap, + legendComponent = , + legendData, + legendPosition = ChartCommonStyles.legend.position, + legendDirection = 'ltr', + name, + padding, + patternScale, + showAxis = true, + themeColor, + + // destructure last + theme = getChartTheme(themeColor, showAxis), + containerComponent = , + legendOrientation = theme.legend.orientation as any, + height = theme.chart.height, + width = theme.chart.width, + ...rest +}: ChartProps) => { + const defaultPadding = { + bottom: getPaddingForSide('bottom', padding, theme.chart.padding), + left: getPaddingForSide('left', padding, theme.chart.padding), + right: getPaddingForSide('right', padding, theme.chart.padding), + top: getPaddingForSide('top', padding, theme.chart.padding) + }; + + const { defaultColorScale, defaultPatternScale, isPatternDefs, patternId } = useDefaultPatternProps({ + colorScale, + patternScale, + hasPatterns, + themeColorScale: theme.chart.colorScale as string[] + }); + + // Add pattern props for legend tooltip + let labelComponent; + if ( + containerComponent.props.labelComponent && + containerComponent.props.labelComponent.type.displayName === 'ChartLegendTooltip' + ) { + labelComponent = cloneElement(containerComponent.props.labelComponent, { + theme, + ...(defaultPatternScale && { patternScale: defaultPatternScale }), + ...containerComponent.props.labelComponent.props + }); + } + + // Clone so users can override container props + const container = cloneElement(containerComponent, { + desc: ariaDesc, + title: ariaTitle, + theme, + ...containerComponent.props, + className: getClassName({ className: containerComponent.props.className }), // Override VictoryContainer class name + ...(labelComponent && { labelComponent }), // Override label component props + ...(themeColor === ChartThemeColor.skeleton && { labelComponent: }) // Omit cursor and tooltips + }); + + let legendXOffset = 0; + if (legendDirection === 'rtl') { + legendXOffset = getLegendMaxTextWidth(legendData, theme); + } + + const legend = cloneElement(legendComponent, { + data: legendData, + ...(name && { name: `${name}-${(legendComponent as any).type.displayName}` }), + orientation: legendOrientation, + theme, + themeColor, + ...(legendDirection === 'rtl' && { + dataComponent: legendComponent.props.dataComponent ? ( + cloneElement(legendComponent.props.dataComponent, { transform: `translate(${legendXOffset})` }) + ) : ( + + ) + }), + ...(legendDirection === 'rtl' && { + labelComponent: legendComponent.props.labelComponent ? ( + cloneElement(legendComponent.props.labelComponent, { direction: 'rtl', dx: legendXOffset - 30 }) + ) : ( + + ) + }), + ...legendComponent.props + }); + + // Returns a computed legend + const getLegend = () => { + if (!legend.props.data) { + return null; + } + let dx = 0; + let dy = 0; + let xAxisLabelHeight = 0; + let legendTitleHeight = legend.props.title ? 10 : 0; + + // Adjust for axis label + Children.toArray(children).map((child: any) => { + if (child.type.role === 'axis' && child.props.label && child.props.fixAxisLabelHeight) { + xAxisLabelHeight = getLabelTextSize({ text: child.props.label, theme }).height + 10; + legendTitleHeight = 0; + } + }); + + if (legendPosition === 'bottom') { + dy += xAxisLabelHeight + legendTitleHeight; + } else if (legendPosition === 'bottom-left') { + dy += xAxisLabelHeight + legendTitleHeight; + dx = -10; + } + + // Adjust legend position when axis is hidden + if (!showAxis) { + dy -= chart_legend_Margin.value; + } + + return getComputedLegend({ + allowWrap: legendAllowWrap === true || typeof legendAllowWrap === 'function', + chartType: 'chart', + colorScale, + dx, + dy, + height, + legendComponent: legend, + padding: defaultPadding, + position: legendPosition, + theme, + themeColor, + width, + ...(defaultPatternScale && { patternScale: defaultPatternScale }) + }); + }; + + // Render children + const renderChildren = () => + Children.toArray(children).map((child, index) => { + if (isValidElement(child)) { + const { ...childProps } = child.props as any; + return cloneElement(child, { + colorScale, + ...(defaultPatternScale && { patternScale: defaultPatternScale }), + ...(name && + typeof (child as any).name !== undefined && { + name: `${name}-${(child as any).type.displayName}-${index}` + }), + theme, + themeColor, + ...childProps, + ...((child as any).type.displayName === 'ChartPie' && { + data: mergePatternData(childProps.data, defaultPatternScale) + }) // Override child props + }); + } + return child; + }); + + // Callback to compliment legendAllowWrap + const computedLegend = getLegend(); + useEffect(() => { + if (computedLegend?.props && typeof legendAllowWrap === 'function') { + const extraHeight = getLegendItemsExtraHeight({ + legendData: computedLegend.props.data, + legendOrientation: computedLegend.props.orientation, + legendProps: computedLegend.props, + theme + }); + legendAllowWrap(extraHeight); + } + }, [computedLegend, legendAllowWrap, theme, width]); + + // Note: containerComponent is required for theme + return ( + + {renderChildren()} + {computedLegend} + {isPatternDefs && getPatternDefs({ patternId, colorScale: defaultColorScale })} + + ); +}; +Chart.displayName = 'Chart'; + +hoistNonReactStatics(Chart, VictoryChart); diff --git a/packages/react-charts/src/victory/components/Chart/__snapshots__/Chart.test.tsx.snap b/packages/react-charts/src/victory/components/Chart/__snapshots__/Chart.test.tsx.snap new file mode 100644 index 00000000000..a4fce2ae5da --- /dev/null +++ b/packages/react-charts/src/victory/components/Chart/__snapshots__/Chart.test.tsx.snap @@ -0,0 +1,1228 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Chart 1`] = ` + +
    + + + + + + + + 0.2 + + + + + + + + 0.4 + + + + + + + + 0.6 + + + + + + + + 0.8 + + + + + + + + 1.0 + + + + + + + + + + + 0.2 + + + + + + + + 0.4 + + + + + + + + 0.6 + + + + + + + + 0.8 + + + + + + + + 1.0 + + + + + +
    + +
    +
    + +`; + +exports[`Chart 2`] = ` + +
    + + + + + + + + 0.2 + + + + + + + + 0.4 + + + + + + + + 0.6 + + + + + + + + 0.8 + + + + + + + + 1.0 + + + + + + + + + + + 0.2 + + + + + + + + 0.4 + + + + + + + + 0.6 + + + + + + + + 0.8 + + + + + + + + 1.0 + + + + + +
    + +
    +
    +
    +`; + +exports[`renders axis and component children 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + + + + + + + + 1.5 + + + + + + + + 2.0 + + + + + + + + 2.5 + + + + + + + + 3.0 + + + + + + + + 3.5 + + + + + + + + 4.0 + + + + + + + + + + + 2 + + + + + + + + 4 + + + + + + + + 6 + + + + + + + + 8 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartArea/ChartArea.test.tsx b/packages/react-charts/src/victory/components/ChartArea/ChartArea.test.tsx new file mode 100644 index 00000000000..cec3c0c45ef --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartArea/ChartArea.test.tsx @@ -0,0 +1,23 @@ +import { render } from '@testing-library/react'; +import { ChartArea } from '../ChartArea/ChartArea'; + +Object.values([true, false]).forEach(() => { + test('ChartArea', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartArea/ChartArea.tsx b/packages/react-charts/src/victory/components/ChartArea/ChartArea.tsx similarity index 94% rename from packages/react-charts/src/components/ChartArea/ChartArea.tsx rename to packages/react-charts/src/victory/components/ChartArea/ChartArea.tsx index ac4c9799791..0978e7d8eb7 100644 --- a/packages/react-charts/src/components/ChartArea/ChartArea.tsx +++ b/packages/react-charts/src/victory/components/ChartArea/ChartArea.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -20,18 +20,17 @@ import { VictoryStyleInterface } from 'victory-core'; import { VictoryArea, VictoryAreaProps, VictoryAreaTTargetType } from 'victory-area'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getTheme } from '../ChartUtils'; - -export enum ChartAreaSortOrder { - ascending = 'ascending', - descending = 'descending' -} +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-area/src/index.d.ts + * ChartArea renders a dataset as a single area path. Since ChartArea renders only a single element to represent a + * dataset rather than individual elements for each data point, some of its behavior is different from other Victory + * based components. Pay special attention to style and events props, and take advantage of ChartVoronoiContainer to + * enable tooltips. ChartArea can be composed with Chart to create area charts. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-area/src/victory-area.tsx */ export interface ChartAreaProps extends VictoryAreaProps { /** @@ -130,7 +129,7 @@ export interface ChartAreaProps extends VictoryAreaProps { * Since ChartArea only renders a single element, the eventKey property is not used. * The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -222,7 +221,7 @@ export interface ChartAreaProps extends VictoryAreaProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -237,7 +236,7 @@ export interface ChartAreaProps extends VictoryAreaProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -312,6 +311,7 @@ export interface ChartAreaProps extends VictoryAreaProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -323,7 +323,7 @@ export interface ChartAreaProps extends VictoryAreaProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -381,14 +381,6 @@ export interface ChartAreaProps extends VictoryAreaProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -434,15 +426,14 @@ export interface ChartAreaProps extends VictoryAreaProps { export const ChartArea: React.FunctionComponent = ({ containerComponent = , themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartAreaProps) => { // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { theme, ...containerComponent.props }); diff --git a/packages/react-charts/src/victory/components/ChartArea/__snapshots__/ChartArea.test.tsx.snap b/packages/react-charts/src/victory/components/ChartArea/__snapshots__/ChartArea.test.tsx.snap new file mode 100644 index 00000000000..2dbee18d2fd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartArea/__snapshots__/ChartArea.test.tsx.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartArea 1`] = ` + +
    + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartArea 2`] = ` + +
    + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartArea/examples/ChartArea.md b/packages/react-charts/src/victory/components/ChartArea/examples/ChartArea.md new file mode 100644 index 00000000000..8211352198d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartArea/examples/ChartArea.md @@ -0,0 +1,60 @@ +--- +id: Area chart +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartArea', + 'ChartAxis', + 'ChartGroup', + 'ChartThreshold', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- +import { createRef } from 'react'; +import { Chart, ChartArea, ChartAxis, ChartGroup, ChartThreshold, ChartThemeColor, ChartLegendTooltip, ChartVoronoiContainer, createContainer } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic with right aligned legend + +```ts file = "ChartAreaRightAlignedLegend.tsx" + +``` + +### Teal with bottom aligned legend and axis label + +This demonstrates how to combine cursor and voronoi containers to display tooltips along with a cursor. + +```ts file = "ChartAreaBottomLegend.tsx" + +``` + +### Multi-color (unordered) bottom-left aligned legend and responsive container +```ts file = "ChartAreaMultiColorResponsive.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` +- The `theme` and `themeColor` props should be applied at the most top level component +- Use `ChartGroup` to apply theme color scales and other properties to multiple components + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaBottomLegend.tsx b/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaBottomLegend.tsx new file mode 100644 index 00000000000..29e88b6f6c2 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaBottomLegend.tsx @@ -0,0 +1,87 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartThemeColor, + ChartLegendTooltip, + createContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + x: string; + y: number; +} + +export const ChartAreaBottomLegend: React.FunctionComponent = () => { + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData = [ + { childName: 'cats', name: 'Cats' }, + { childName: 'dogs', name: 'Dogs' }, + { childName: 'birds', name: 'Birds' } + ]; + + const catsData: PetData[] = [ + { x: '2015', y: 3 }, + { x: '2016', y: 4 }, + { x: '2017', y: 8 }, + { x: '2018', y: 6 } + ]; + + const dogsData: PetData[] = [ + { x: '2015', y: 2 }, + { x: '2016', y: 3 }, + { x: '2017', y: 4 }, + { x: '2018', y: 5 }, + { x: '2019', y: 6 } + ]; + + const birdsData: PetData[] = [ + { x: '2015', y: 1 }, + { x: '2016', y: 2 }, + { x: '2017', y: 3 }, + { x: '2018', y: 2 }, + { x: '2019', y: 4 } + ]; + + return ( +
    + `${datum.y}`} + labelComponent={ datum.x} />} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom" + height={250} + name="chart2" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.teal} + width={650} + > + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaMultiColorResponsive.tsx b/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaMultiColorResponsive.tsx new file mode 100644 index 00000000000..8f6a91ca622 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaMultiColorResponsive.tsx @@ -0,0 +1,91 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; + +interface PetData { + name: string; + x: string; + y: number; +} +export const ChartAreaMultiColorResponsive: React.FunctionComponent = () => { + const [width, setWidth] = React.useState(0); + const containerRef = React.useRef(null); + + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + + const dogsData: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 3 }, + { name: 'Dogs', x: '2017', y: 4 }, + { name: 'Dogs', x: '2018', y: 5 }, + { name: 'Dogs', x: '2019', y: 6 } + ]; + + const birdsData: PetData[] = [ + { name: 'Birds', x: '2015', y: 1 }, + { name: 'Birds', x: '2016', y: 2 }, + { name: 'Birds', x: '2017', y: 3 }, + { name: 'Birds', x: '2018', y: 2 }, + { name: 'Birds', x: '2019', y: 4 } + ]; + + const legendData = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]; + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + React.useEffect(() => { + const observer = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer(); + }; + }, []); + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendPosition="bottom-left" + height={225} + name="chart3" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaRightAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaRightAlignedLegend.tsx new file mode 100644 index 00000000000..0a88f0bc89e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartArea/examples/ChartAreaRightAlignedLegend.tsx @@ -0,0 +1,67 @@ +import { Chart, ChartArea, ChartAxis, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartAreaRightAlignedLegend: React.FunctionComponent = () => { + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + + const dogsData: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 3 }, + { name: 'Dogs', x: '2017', y: 4 }, + { name: 'Dogs', x: '2018', y: 5 }, + { name: 'Dogs', x: '2019', y: 6 } + ]; + + const birdsData: PetData[] = [ + { name: 'Birds', x: '2015', y: 1 }, + { name: 'Birds', x: '2016', y: 2 }, + { name: 'Birds', x: '2017', y: 3 }, + { name: 'Birds', x: '2018', y: 2 }, + { name: 'Birds', x: '2019', y: 4 } + ]; + + const legendData = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={200} + maxDomain={{ y: 9 }} + name="chart1" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + width={800} + > + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartAxis/ChartAxis.test.tsx b/packages/react-charts/src/victory/components/ChartAxis/ChartAxis.test.tsx new file mode 100644 index 00000000000..1e85ca81f32 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartAxis/ChartAxis.test.tsx @@ -0,0 +1,57 @@ +import { render } from '@testing-library/react'; +import { Chart } from '../Chart/Chart'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartLine } from '../ChartLine/ChartLine'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartAxis } from './ChartAxis'; + +Object.values([true, false]).forEach(() => { + test('ChartAxis', () => { + const { asFragment } = render(} />); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + + + + + + + } /> + } /> + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartAxis/ChartAxis.tsx b/packages/react-charts/src/victory/components/ChartAxis/ChartAxis.tsx similarity index 89% rename from packages/react-charts/src/components/ChartAxis/ChartAxis.tsx rename to packages/react-charts/src/victory/components/ChartAxis/ChartAxis.tsx index 1a794bc1083..4d48dd5a684 100644 --- a/packages/react-charts/src/components/ChartAxis/ChartAxis.tsx +++ b/packages/react-charts/src/victory/components/ChartAxis/ChartAxis.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -15,13 +15,16 @@ import { LabelProps } from 'victory-core'; import { VictoryAxis, VictoryAxisProps, VictoryAxisTTargetType } from 'victory-axis'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getAxisTheme, getTheme } from '../ChartUtils'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getComponentTheme, getTheme } from '../ChartUtils/chart-theme'; +import { getAxisTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-axis/src/index.d.ts + * ChartAxis renders a single axis which can be used on its own or composed with Chart. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-axis/src/index.d.ts */ export interface ChartAxisProps extends VictoryAxisProps { /** @@ -114,7 +117,7 @@ export interface ChartAxisProps extends VictoryAxisProps { * single element by index rather than an entire set. The eventHandlers object * should be given as an object whose keys are standard event names (i.e. onClick) * and whose values are event callbacks. The return value of an event handler - * be used to modify other elemnts. The return value should be given as an object or + * be used to modify other elements. The return value should be given as an object or * an array of objects with optional target and eventKey keys, and a mutation * key whose value is a function. The target and eventKey keys will default to those * corresponding to the element the event handler was attached to. The mutation @@ -154,6 +157,10 @@ export interface ChartAxisProps extends VictoryAxisProps { * @propType object[] */ externalEventMutations?: EventCallbackInterface[]; + /** + * When true, this prop adjusts the height between the axis label and bottom positioned legend + */ + fixAxisLabelHeight?: boolean; /** * When true, this prop reduces the number of tick labels to fit the length of the axis. * Labels are removed at approximately even intervals from the original array of labels. @@ -204,7 +211,7 @@ export interface ChartAxisProps extends VictoryAxisProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -219,7 +226,7 @@ export interface ChartAxisProps extends VictoryAxisProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -230,7 +237,9 @@ export interface ChartAxisProps extends VictoryAxisProps { */ minDomain?: number | { x?: number; y?: number }; /** - * ChartAxis uses the standard name prop + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. */ name?: string; /** @@ -296,6 +305,7 @@ export interface ChartAxisProps extends VictoryAxisProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -311,7 +321,7 @@ export interface ChartAxisProps extends VictoryAxisProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -334,7 +344,7 @@ export interface ChartAxisProps extends VictoryAxisProps { * determine relative layout for components in Chart. Functional styles may be defined for * grid, tick, and tickLabel style properties, and they will be evaluated with each tick. * - * note: When a component is rendered as a child of another Victory component, or within a custom + * Note: When a component is rendered as a child of another Victory component, or within a custom * element with standalone={false} parent styles will be applied to the enclosing tag. * Many styles that can be applied to a parent will not be expressed when applied to a . * @@ -380,14 +390,6 @@ export interface ChartAxisProps extends VictoryAxisProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The tickComponent prop takes in an entire component which will be used * to create tick lines. The new element created from the passed tickComponent @@ -443,26 +445,50 @@ export interface ChartAxisProps extends VictoryAxisProps { } export const ChartAxis: React.FunctionComponent = ({ + axisLabelComponent = , containerComponent = , + name, showGrid = false, themeColor, - themeVariant, - + tickLabelComponent = , // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartAxisProps) => { + const componentTheme = getComponentTheme(themeColor); + // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { theme, ...containerComponent.props }); + const getAxisLabelComponent = () => + cloneElement(axisLabelComponent, { + ...(name && { + id: () => `${name}-${(axisLabelComponent as any).type.displayName}` + }), + ...axisLabelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle + }); + + const getTickLabelComponent = () => + cloneElement(tickLabelComponent, { + ...(name && { + id: (props: any) => `${name}-${(tickLabelComponent as any).type.displayName}-${props.index}` + }), + ...tickLabelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle + }); + // Note: containerComponent is required for theme return ( ); diff --git a/packages/react-charts/src/victory/components/ChartAxis/__snapshots__/ChartAxis.test.tsx.snap b/packages/react-charts/src/victory/components/ChartAxis/__snapshots__/ChartAxis.test.tsx.snap new file mode 100644 index 00000000000..2a2d7f87f09 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartAxis/__snapshots__/ChartAxis.test.tsx.snap @@ -0,0 +1,789 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartAxis 1`] = ` + +
    + + + + + + + 0.0 + + + + + + + + 0.2 + + + + + + + + 0.4 + + + + + + + + 0.6 + + + + + + + + 0.8 + + + + + + + + 1.0 + + + + +
    + +
    +
    + +`; + +exports[`ChartAxis 2`] = ` + +
    + + + + + + + 0.0 + + + + + + + + 0.2 + + + + + + + + 0.4 + + + + + + + + 0.6 + + + + + + + + 0.8 + + + + + + + + 1.0 + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + 3 + + + + + + + + 4 + + + + + + + + + + + 2 + + + + + + + + 5 + + + + + + + + 8 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/components/ChartBar/ChartBar.test.tsx b/packages/react-charts/src/victory/components/ChartBar/ChartBar.test.tsx similarity index 77% rename from packages/react-charts/src/components/ChartBar/ChartBar.test.tsx rename to packages/react-charts/src/victory/components/ChartBar/ChartBar.test.tsx index e67f9b00c6b..3a1fee8d1b3 100644 --- a/packages/react-charts/src/components/ChartBar/ChartBar.test.tsx +++ b/packages/react-charts/src/victory/components/ChartBar/ChartBar.test.tsx @@ -1,18 +1,17 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Chart } from '../Chart'; +import { render } from '@testing-library/react'; +import { Chart } from '../Chart/Chart'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; import { ChartBar } from './ChartBar'; -import { ChartGroup } from '../ChartGroup'; Object.values([true, false]).forEach(() => { test('ChartBar', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); }); test('renders component data', () => { - const view = shallow( + const { asFragment } = render( { ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-charts/src/components/ChartBar/ChartBar.tsx b/packages/react-charts/src/victory/components/ChartBar/ChartBar.tsx similarity index 95% rename from packages/react-charts/src/components/ChartBar/ChartBar.tsx rename to packages/react-charts/src/victory/components/ChartBar/ChartBar.tsx index 1785293f481..449b79065f6 100644 --- a/packages/react-charts/src/components/ChartBar/ChartBar.tsx +++ b/packages/react-charts/src/victory/components/ChartBar/ChartBar.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -20,13 +20,14 @@ import { VictoryStyleInterface } from 'victory-core'; import { VictoryBar, VictoryBarAlignmentType, VictoryBarProps, VictoryBarTTargetType } from 'victory-bar'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getTheme } from '../ChartUtils'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-bar/src/index.d.ts + * ChartBar renders a dataset as series of bars. ChartBar can be composed with Chart to create bar charts. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-bar/src/index.d.ts */ export interface ChartBarProps extends VictoryBarProps { /** @@ -168,7 +169,7 @@ export interface ChartBarProps extends VictoryBarProps { * The eventKey may optionally be used to select a single element by index rather than an entire * set. The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -254,7 +255,7 @@ export interface ChartBarProps extends VictoryBarProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -269,7 +270,7 @@ export interface ChartBarProps extends VictoryBarProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -305,6 +306,7 @@ export interface ChartBarProps extends VictoryBarProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -348,6 +350,7 @@ export interface ChartBarProps extends VictoryBarProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -359,7 +362,7 @@ export interface ChartBarProps extends VictoryBarProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -417,14 +420,6 @@ export interface ChartBarProps extends VictoryBarProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -470,14 +465,13 @@ export interface ChartBarProps extends VictoryBarProps { export const ChartBar: React.FunctionComponent = ({ containerComponent = , themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartBarProps) => { // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { theme, ...containerComponent.props }); @@ -488,4 +482,4 @@ export const ChartBar: React.FunctionComponent = ({ ChartBar.displayName = 'ChartBar'; // Note: VictoryBar.getDomain & VictoryBar.role must be hoisted -hoistNonReactStatics(ChartBar, VictoryBar); +hoistNonReactStatics(ChartBar, VictoryBar, { getBaseProps: true }); diff --git a/packages/react-charts/src/victory/components/ChartBar/__snapshots__/ChartBar.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBar/__snapshots__/ChartBar.test.tsx.snap new file mode 100644 index 00000000000..489cd174ea7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBar/__snapshots__/ChartBar.test.tsx.snap @@ -0,0 +1,747 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBar 1`] = ` + +
    + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartBar 2`] = ` + +
    + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cats + + + + + + + + Dogs + + + + + + + + Birds + + + + + + + + Mice + + + + + + + + + + + 2 + + + + + + + + 4 + + + + + + + + 6 + + + + + + + + 8 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBar/examples/ChartBar.md b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBar.md new file mode 100644 index 00000000000..29f57c11b9e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBar.md @@ -0,0 +1,76 @@ +--- +id: Bar chart +section: components +subsection: charts +propComponents: ['Chart', 'ChartAxis', 'ChartBar', 'ChartGroup', 'ChartLabel', 'ChartVoronoiContainer'] +hideDarkMode: true +--- + +import { Chart, ChartAxis, ChartBar, ChartGroup, ChartLabel, ChartThemeColor, ChartTooltip, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; +import { VictoryZoomContainer } from 'victory-zoom-container'; +import t_global_color_status_danger_100 from '@patternfly/react-tokens/dist/esm/t_global_color_status_danger_100'; +import t_global_color_status_info_100 from '@patternfly/react-tokens/dist/esm/t_global_color_status_info_100'; +import t_global_color_status_warning_100 from '@patternfly/react-tokens/dist/esm/t_global_color_status_warning_100'; + +## Introduction + +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples + +### Basic with right aligned legend + +```ts file = "ChartBarRightAlignedLegend.tsx" + +``` + +### Purple with bottom aligned legend + +This demonstrates an alternate way of applying tooltips using data labels. + +```ts file = "ChartBarBottomLegend.tsx" +``` + +### Multi-color (ordered) with bottom-left aligned legend + +This demonstrates zoom for both the x and y axis. + +```ts file = "ChartBarMultiColorOrdered.tsx" + +``` + +### Single with right aligned legend + +```ts file = "ChartBarSingleLegend.tsx" +``` + +### Alerts timeline + +A gnatt-like chart using `y` and `y0` data properties for alert start/end dates + +```ts file = "ChartBarAlertsTimeline.tsx" + +``` + +## Documentation + +### Tips + +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` +- The `theme` and `themeColor` props should be applied at the most top level component +- Use `ChartGroup` to apply theme color scales and other properties to multiple components + +### Note + +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarAlertsTimeline.tsx b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarAlertsTimeline.tsx new file mode 100644 index 00000000000..00abbd0699f --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarAlertsTimeline.tsx @@ -0,0 +1,193 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartGroup, + ChartLabel, + ChartTooltip, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import t_global_color_status_danger_100 from '@patternfly/react-tokens/dist/esm/t_global_color_status_danger_100'; +import t_global_color_status_info_100 from '@patternfly/react-tokens/dist/esm/t_global_color_status_info_100'; +import t_global_color_status_warning_100 from '@patternfly/react-tokens/dist/esm/t_global_color_status_warning_100'; + +interface AlertData { + y0: Date; + y: Date; + severity: string; + x?: number; + fill?: string; +} + +export const ChartBarAlertsTimeline: React.FunctionComponent = () => { + // Start = y0, end = y + const alerts = [ + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-09T02:30:00'), severity: 'danger' }, + { y0: new Date('2024-08-10T05:30:00'), y: new Date('2024-08-10T20:00:00'), severity: 'danger' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'danger' } + ], + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-07T02:30:00'), severity: 'danger' }, + { y0: new Date('2024-08-07T07:30:00'), y: new Date('2024-08-09T09:30:00'), severity: 'danger' }, + { y0: new Date('2024-08-10T05:30:00'), y: new Date('2024-08-10T20:00:00'), severity: 'warn' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'danger' } + ], + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-07T02:30:00'), severity: 'danger' }, + { y0: new Date('2024-08-08T07:30:00'), y: new Date('2024-08-09T09:30:00'), severity: 'danger' }, + { y0: new Date('2024-08-10T05:30:00'), y: new Date('2024-08-10T20:00:00'), severity: 'info' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'warn' } + ], + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-08T02:30:00'), severity: 'info' }, + { y0: new Date('2024-08-08T07:30:00'), y: new Date('2024-08-09T09:30:00'), severity: 'info' }, + { y0: new Date('2024-08-10T05:30:00'), y: new Date('2024-08-11T20:00:00'), severity: 'warn' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'info' } + ], + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-07T02:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-08T07:30:00'), y: new Date('2024-08-09T09:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-09T11:30:00'), y: new Date('2024-08-10T20:00:00'), severity: 'warn' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'warn' } + ], + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-08T02:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-08T07:30:00'), y: new Date('2024-08-09T09:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-10T05:30:00'), y: new Date('2024-08-11T20:00:00'), severity: 'warn' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'warn' } + ], + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-07T02:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-07T04:30:00'), y: new Date('2024-08-08T05:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-08T07:30:00'), y: new Date('2024-08-09T09:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-10T05:30:00'), y: new Date('2024-08-10T20:00:00'), severity: 'warn' }, + { y0: new Date('2024-08-11T05:30:00'), y: new Date('2024-08-11T20:00:00'), severity: 'warn' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'warn' } + ], + [ + { y0: new Date('2024-08-06T01:30:00'), y: new Date('2024-08-08T02:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-08T07:30:00'), y: new Date('2024-08-09T09:30:00'), severity: 'warn' }, + { y0: new Date('2024-08-10T05:30:00'), y: new Date('2024-08-11T20:00:00'), severity: 'warn' }, + { y0: new Date('2024-08-12T10:00:00'), y: new Date('2024-08-13T10:30:00'), severity: 'warn' } + ] + ]; + + const legendData = [ + { name: 'Danger', symbol: { fill: t_global_color_status_danger_100.var } }, + + { name: 'Info', symbol: { fill: t_global_color_status_info_100.var } }, + + { name: 'Warning', symbol: { fill: t_global_color_status_warning_100.var } } + ]; + + const getSeverityColor = (severity) => { + if (severity === 'danger') { + return t_global_color_status_danger_100.var; + } else if (severity === 'warn') { + return t_global_color_status_warning_100.var; + } else { + return t_global_color_status_info_100.var; + } + }; + + const formatDate = (date: Date, isTime: boolean) => { + const dateString = date?.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); + const timeString = date?.toLocaleTimeString('en-US', { hour12: false }); + return isTime ? `${dateString} ${timeString}` : dateString; + }; + + const getChart = (alert: AlertData[], index: number) => { + const data: AlertData[] = []; + + alert?.map((datum) => { + data.push({ + ...datum, + x: alerts.length - index, + fill: getSeverityColor(datum.severity) + }); + }); + + if (data?.length === 0) { + return null; + } + return ( + datum.fill, + stroke: ({ datum }) => datum.fill + } + }} + /> + ); + }; + + return ( +
    + -(x - x0) / 2} // Position tooltip so pointer appears centered + dy={-5} // Position tooltip so pointer appears above bar + labelComponent={} + orientation="top" // Mimic bullet chart tooltip orientation + /> + } + labels={({ datum }) => + `Severity: ${datum.severity}\nStart: ${formatDate(new Date(datum.y0), true)}\nEnd: ${formatDate(new Date(datum.y), true)}` + } + /> + } + domainPadding={{ x: [20, 20], y: [20, 20] }} + legendData={legendData} + legendPosition="bottom-left" + height={400} + name="chart5" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 100, + right: 50, // Adjusted to accommodate tooltip + top: 50 + }} + width={450} + > + new Date(t).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })} + tickValues={[ + new Date('2024-08-06T00:00:00'), + new Date('2024-08-08T00:00:00'), + new Date('2024-08-10T00:00:00'), + new Date('2024-08-12T00:00:00') + ]} + /> + } + label="Incidents" + padding={{ top: 20, bottom: 60 }} + style={{ + axis: { + stroke: 'transparent' + }, + ticks: { + stroke: 'transparent' + }, + tickLabels: { + fill: 'transparent' + } + }} + /> + {alerts.map((alert, index) => getChart(alert, index))} + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarBottomLegend.tsx b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarBottomLegend.tsx new file mode 100644 index 00000000000..64998f46dcb --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarBottomLegend.tsx @@ -0,0 +1,83 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartGroup, + ChartThemeColor, + ChartTooltip +} from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; + label: string; +} + +export const ChartBarBottomLegend: React.FunctionComponent = () => { + const label = + () => + ({ datum }) => + `${datum.name}: ${datum.y}`; + + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: 1, label }, + { name: 'Cats', x: '2016', y: 2, label }, + { name: 'Cats', x: '2017', y: 5, label }, + { name: 'Cats', x: '2018', y: 3, label } + ]; + + const dogsData: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2, label }, + { name: 'Dogs', x: '2016', y: 1, label }, + { name: 'Dogs', x: '2017', y: 7, label }, + { name: 'Dogs', x: '2018', y: 4, label } + ]; + + const birdsData: PetData[] = [ + { name: 'Birds', x: '2015', y: 4, label }, + { name: 'Birds', x: '2016', y: 4, label }, + { name: 'Birds', x: '2017', y: 9, label }, + { name: 'Birds', x: '2018', y: 7, label } + ]; + + const miceData: PetData[] = [ + { name: 'Mice', x: '2015', y: 3, label }, + { name: 'Mice', x: '2016', y: 3, label }, + { name: 'Mice', x: '2017', y: 8, label }, + { name: 'Mice', x: '2018', y: 5, label } + ]; + + const legendData = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + + return ( +
    + + + + + } /> + } /> + } /> + } /> + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarMultiColorOrdered.tsx b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarMultiColorOrdered.tsx new file mode 100644 index 00000000000..6d7dc460d28 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarMultiColorOrdered.tsx @@ -0,0 +1,71 @@ +import { Chart, ChartAxis, ChartBar, ChartGroup, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { VictoryZoomContainer } from 'victory-zoom-container'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartBarMultiColorOrdered: React.FunctionComponent = () => { + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const dogsData: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const birdsData: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + + const miceData: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + const legendData = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + return ( +
    + } + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendPosition="bottom-left" + height={400} + name="chart3" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 100, // Adjusted to accommodate tooltip + top: 50 + }} + themeColor={ChartThemeColor.multiOrdered} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarRightAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarRightAlignedLegend.tsx new file mode 100644 index 00000000000..5254fa71226 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarRightAlignedLegend.tsx @@ -0,0 +1,73 @@ +import { Chart, ChartAxis, ChartBar, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartBarRightAlignedLegend: React.FunctionComponent = () => { + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const dogsData: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const birdsData: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + + const miceData: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + const legendData = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domain={{ y: [0, 9] }} + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + name="chart1" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + width={600} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarSingleLegend.tsx b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarSingleLegend.tsx new file mode 100644 index 00000000000..3991e5ffe64 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBar/examples/ChartBarSingleLegend.tsx @@ -0,0 +1,45 @@ +import { Chart, ChartBar, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartBarSingleLegend: React.FunctionComponent = () => { + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const legendData = [{ name: 'Cats' }]; + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domain={{ y: [0, 9] }} + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + name="chart4" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + width={600} + > + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/ChartBoxPlot.test.tsx b/packages/react-charts/src/victory/components/ChartBoxPlot/ChartBoxPlot.test.tsx new file mode 100644 index 00000000000..72a7b5c80d6 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/ChartBoxPlot.test.tsx @@ -0,0 +1,26 @@ +import { render } from '@testing-library/react'; +import { Chart } from '../Chart/Chart'; +import { ChartBoxPlot } from './ChartBoxPlot'; + +Object.values([true, false]).forEach(() => { + test('ChartBar', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/ChartBoxPlot.tsx b/packages/react-charts/src/victory/components/ChartBoxPlot/ChartBoxPlot.tsx new file mode 100644 index 00000000000..1879c95fd50 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/ChartBoxPlot.tsx @@ -0,0 +1,699 @@ +import { cloneElement } from 'react'; +import hoistNonReactStatics from 'hoist-non-react-statics'; +import { + AnimatePropTypeInterface, + CategoryPropType, + D3Scale, + DataGetterPropType, + DomainPropType, + DomainPaddingPropType, + EventCallbackInterface, + EventPropTypeInterface, + OriginType, + PaddingProps, + RangePropType, + ScalePropType, + SortOrderPropType, + StringOrNumberOrCallback, + StringOrNumberOrList, + VictoryStyleInterface, + OrientationTypes +} from 'victory-core'; +import { + VictoryBoxPlot, + VictoryBoxPlotLabelOrientationInterface, + VictoryBoxPlotLabelType, + VictoryBoxPlotProps +} from 'victory-box-plot'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getTheme } from '../ChartUtils/chart-theme'; + +/** + * ChartBoxPlot renders a box plot to describe the distribution of a set of data. Data for ChartBoxPlot may be given + * with summary statistics pre-calculated (min, median, max, q1, q3), or as an array of raw data. ChartBoxPlot can be + * composed with Chart to create box plot charts. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-bar/src/index.d.ts + * + */ +export interface ChartBoxPlotProps extends VictoryBoxPlotProps { + /** + * The animate prop specifies props for VictoryAnimation to use. + * The animate prop should also be used to specify enter and exit + * transition configurations with the `onExit` and `onEnter` namespaces respectively. + * + * @propType boolean | object + * @example {duration: 500, onExit: () => {}, onEnter: {duration: 500, before: () => ({y: 0})})} + */ + animate?: boolean | AnimatePropTypeInterface; + /** + * The boxWidth prop specifies how wide each box should be. If the whiskerWidth prop is not set, this prop will also + * determine the width of the whisker crosshair. + */ + boxWidth?: number; + /** + * The categories prop specifies how categorical data for a chart should be ordered. + * This prop should be given as an array of string values, or an object with + * these arrays of values specified for x and y. If this prop is not set, + * categorical data will be plotted in the order it was given in the data array + * + * @propType string[] | { x: string[], y: string[] } + * @example ["dogs", "cats", "mice"] + */ + categories?: CategoryPropType; + /** + * The containerComponent prop takes an entire component which will be used to + * create a container element for standalone charts. + * The new element created from the passed containerComponent wil be provided with + * these props from ChartBoxPlot: height, width, children + * (the chart itself) and style. Props that are not provided by the + * child chart component include title and desc, both of which + * are intended to add accessibility to Victory components. The more descriptive these props + * are, the more accessible your data will be for people using screen readers. + * Any of these props may be overridden by passing in props to the supplied component, + * or modified or ignored within the custom component itself. If a dataComponent is + * not provided, ChartBoxPlot will use the default ChartContainer component. + * + * @example + */ + containerComponent?: React.ReactElement; + /** + * The data prop for ChartBoxPlot may be given in a variety of formats: + * + * @example + * As an array of standard data objects with values specified for x and y When given in this format, repeated values + * for x will be used for calculating summary statistics + * + * data={[ + * { x: 1, y: 2 }, + * { x: 1, y: 3 }, + * { x: 1, y: 5 }, + * { x: 2, y: 1 }, + * { x: 2, y: 4 }, + * { x: 2, y: 5 }, + * ... + * ]} + * + * @example As an array of data objects where y is given as an array of values When given in this format, array values + * are used for calculating summary statistics. + * + * data={[ + * { x: 1, y: [1, 2, 3, 5] }, + * { x: 2, y: [3, 2, 8, 10] }, + * { x: 3, y: [2, 8, 6, 5] }, + * { x: 4, y: [1, 3, 2, 9] } + * ]} + * + * @example As an array of data objects with pre-calculated summary statistics(min, median, max, q1, q3) When given in + * this format, ChartBoxPlot will not perform statistical analysis. Pre-calculating summary statistics for large + * datasets will improve performance. + * + * data={[ + * { x: 1, min: 2, median: 5, max: 10, q1: 3, q3: 7 }, + * { x: 2, min: 1, median: 4, max: 9, q1: 3, q3: 6 }, + * { x: 3, min: 1, median: 6, max: 12, q1: 4, q3: 10 }, + * ]} + * + * Use the x, y, min, max, median, q1, and q3 data accessor props to specify custom data formats. + */ + data?: any[]; + /** + * The domain prop describes the range of values your chart will cover. This prop can be + * given as a array of the minimum and maximum expected values for your bar chart, + * or as an object that specifies separate arrays for x and y. + * If this prop is not provided, a domain will be calculated from data, or other + * available information. + * + * @propType number[] | { x: number[], y: number[] } + * @example [low, high], { x: [low, high], y: [low, high] } + * + * [-1, 1], {x: [0, 100], y: [0, 1]} + */ + domain?: DomainPropType; + /** + * The domainPadding prop specifies a number of pixels of padding to add to the + * beginning and end of a domain. This prop is useful for explicitly spacing ticks farther + * from the origin to prevent crowding. This prop should be given as an object with + * numbers specified for x and y. + * + * @propType number | number[] | { x: number[], y: number[] } + * @example [left, right], { x: [left, right], y: [bottom, top] } + * + * {x: [10, -10], y: 5} + */ + domainPadding?: DomainPaddingPropType; + /** + * Similar to data accessor props `x` and `y`, this prop may be used to functionally + * assign eventKeys to data + * + * @propType number | string | Function + */ + eventKey?: StringOrNumberOrCallback; + /** + * The event prop take an array of event objects. Event objects are composed of + * a target, an eventKey, and eventHandlers. Targets may be any valid style namespace + * for a given component, so "data" and "labels" are all valid targets for ChartBoxPlot events. + * The eventKey may optionally be used to select a single element by index rather than an entire + * set. The eventHandlers object should be given as an object whose keys are standard + * event names (i.e. onClick) and whose values are event callbacks. The return value + * of an event handler is used to modify elements. The return value should be given + * as an object or an array of objects with optional target and eventKey keys, + * and a mutation key whose value is a function. The target and eventKey keys + * will default to those corresponding to the element the event handler was attached to. + * The mutation function will be called with the calculated props for the individual selected + * element (i.e. a single bar), and the object returned from the mutation function + * will override the props of the selected element via object assignment. + * + * @propType object[] + * @example + * + * events={[ + * { + * target: "data", + * eventKey: "thisOne", + * eventHandlers: { + * onClick: () => { + * return [ + * { + * eventKey: "theOtherOne", + * mutation: (props) => { + * return {style: merge({}, props.style, {fill: "orange"})}; + * } + * }, { + * eventKey: "theOtherOne", + * target: "labels", + * mutation: () => { + * return {text: "hey"}; + * } + * } + * ]; + * } + * } + * } + * ]} + */ + events?: EventPropTypeInterface[]; + /** + * ChartBoxPlot uses the standard externalEventMutations prop. + * + * @propType object[] + */ + externalEventMutations?: EventCallbackInterface[]; + /** + * The groupComponent prop takes an entire component which will be used to + * create group elements for use within container elements. This prop defaults + * to a tag on web, and a react-native-svg tag on mobile + */ + groupComponent?: React.ReactElement; + /** + * The height props specifies the height the svg viewBox of the chart container. + * This value should be given as a number of pixels + */ + height?: number; + /** + * The horizontal prop determines whether the bars will be laid vertically or + * horizontally. The bars will be vertical if this prop is false or unspecified, + * or horizontal if the prop is set to true. + */ + horizontal?: boolean; + /** + * The labelOrientation prop determines where labels are placed relative to their corresponding data. If this prop is + * not set, it will be set to "top" for horizontal charts, and "right" for vertical charts. + */ + labelOrientation?: OrientationTypes | VictoryBoxPlotLabelOrientationInterface; + /** + * When the boolean labels prop is set to true, the values for min, max, median, q1, and q3 will be displayed for + * each box. For more granular label control, use the individual minLabels, maxLabels, medianLabels, q1Labels, and + * q3Labels props. + */ + labels?: boolean; + /** + * Use the max data accessor prop to define the max value of a box plot. + * + * @propType string | array[string] | function + * @example Specify which property in an array of data objects should be used as the max value + * + * max="max_value" + * + * @example Use a function to translate each element in a data array into a max value + * + * max={() => 10} + * + * @example Specify which property in an array of nested data objects should be used as a max value + * + * max="bonds.max", max={["bonds", "max"]} + */ + max?: StringOrNumberOrCallback | string[]; + /** + * The maxComponent prop takes a component instance which will be responsible for rendering an element to represent + * the maximum value of the box plot. The new element created from the passed maxComponent will be provided with the + * following props calculated by ChartBoxPlot: datum, index, scale, style, events, majorWhisker and minorWhisker. + * The majorWhisker and minorWhisker props are given as objects with values for x1, y1, x2 and y2 that describes the + * lines that make up the major and minor whisker. Any of these props may be overridden by passing in props to the + * supplied component, or modified or ignored within the custom component itself. If a maxComponent is not provided, + * ChartBoxPlot will use its default Whisker component. + */ + maxComponent?: React.ReactElement; + /** + * The maxDomain prop defines a maximum domain value for a chart. This prop is useful in situations where the maximum + * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain + * prop is set in addition to maximumDomain, domain will be used. + * + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to + * the y axis. + * + * @example + * + * maxDomain={0} + * maxDomain={{ y: 0 }} + */ + maxDomain?: number | { x?: number; y?: number }; + /** + * The maxLabelComponent prop takes a component instance which will be used to render the label corresponding to the + * maximum value for each box. The new element created from the passed maxLabelComponent will be supplied with the + * following props: x, y, datum, index, scale, verticalAnchor, textAnchor, angle, transform, style and events. Any of + * these props may be overridden by passing in props to the supplied component, or modified or ignored within the + * custom component itself. If maxLabelComponent is omitted, a new ChartLabel will be created with props described + * above. + */ + maxLabelComponent?: React.ReactElement; + /** + * The maxLabels prop defines the labels that will appear above each point. This prop should be given as a boolean, + * an array or as a function of the props corresponding to that label. When given as a boolean value, the max value + * of each datum will be used for the label. + * + * @example + * + * maxLabels={["first", "second", "third"]} + * maxLabels={({ datum }) => Math.round(datum.max)} + */ + maxLabels?: VictoryBoxPlotLabelType; + /** + * Use the median data accessor prop to define the median value of a box plot. + * + * @propType string | array[string] | function + * @example Specify which property in an array of data objects should be used as the median value + * + * median="median_value" + * + * @example Use a function to translate each element in a data array into a median value + * + * median={() => 10} + * + * @example Specify which property in an array of nested data objects should be used as a median value + * + * median="bonds.median", median={["bonds", "median"]} + */ + median?: StringOrNumberOrCallback | string[]; + /** + * The medianComponent prop takes a component instance which will be responsible for rendering an element to represent + * the median value of the box plot. The new element created from the passed medianComponent will be provided with the + * following props calculated by ChartBoxPlot: datum, index, scale, style, events, x1, y1, x2 and y2 Any of these + * props may be overridden by passing in props to the supplied component, or modified or ignored within the custom + * component itself. If a medianComponent is not provided, ChartBoxPlot will use its default Line component. + */ + medianComponent?: React.ReactElement; + /** + * The medianLabelComponent prop takes a component instance which will be used to render the label corresponding to + * the median value for each box. The new element created from the passed medianLabelComponent will be supplied with + * the following props: x, y, datum, index, scale, verticalAnchor, textAnchor, angle, transform, style and events. Any + * of these props may be overridden by passing in props to the supplied component, or modified or ignored within the + * custom component itself. If medianLabelComponent is omitted, a new ChartLabel will be created with props + * described above. + */ + medianLabelComponent?: React.ReactElement; + /** + * The medianLabels prop defines the labels that will appear above each point. This prop should be given as a boolean, + * an array or as a function of the props corresponding to that label. When given as a boolean value, the median value + * of each datum will be used for the label. + * + * @propType string | function | boolean + * @example + * + * medianLabels={["first", "second", "third"]} + * medianLabels={({ datum }) => Math.round(datum.median)} + */ + medianLabels?: VictoryBoxPlotLabelType; + /** + * Use the min data accessor prop to define the min value of a box plot. + * + * @propType string | array[string] | function + * @example Specify which property in an array of data objects should be used as the min value + * + * min="min_value" + * + * @example Use a function to translate each element in a data array into a min value + * + * min={() => 10} + * + * @example Specify which property in an array of nested data objects should be used as a min value + * + * min="bonds.min", min={["bonds", "min"]} + */ + min?: StringOrNumberOrCallback | string[]; + /** + * The minComponent prop takes a component instance which will be responsible for rendering an element to represent + * the minimum value of the box plot. The new element created from the passed minComponent will be provided with the + * following props calculated by ChartBoxPlot: datum, index, scale, style, events, majorWhisker and minorWhisker. + * The majorWhisker and minorWhisker props are given as objects with values for x1, y1, x2 and y2 that describes the + * lines that make up the major and minor whisker. Any of these props may be overridden by passing in props to the + * supplied component, or modified or ignored within the custom component itself. If a minComponent is not provided, + * ChartBoxPlot will use its default Whisker component. + */ + minComponent?: React.ReactElement; + /** + * The minDomain prop defines a minimum domain value for a chart. This prop is useful in situations where the minimum + * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain + * prop is set in addition to minimumDomain, domain will be used. + * + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to + * the y axis. + * + * @example + * + * minDomain={0} + * minDomain={{ y: 0 }} + */ + minDomain?: number | { x?: number; y?: number }; + /** + * The minLabelComponent prop takes a component instance which will be used to render the label corresponding to the + * minimum value for each box. The new element created from the passed minLabelComponent will be supplied with the + * following props: x, y, datum, index, scale, verticalAnchor, textAnchor, angle, transform, style and events. Any of + * these props may be overridden by passing in props to the supplied component, or modified or ignored within the + * custom component itself. If minLabelComponent is omitted, a new ChartLabel will be created with props described + * above. + */ + minLabelComponent?: React.ReactElement; + /** + * The minLabels prop defines the labels that will appear above each point. This prop should be given as a boolean, an + * array or as a function of the props corresponding to that label. When given as a boolean value, the min value of + * each datum will be used for the label. + * + * @propType string | function | boolean + * @example + * + * minLabels={["first", "second", "third"]} + * minLabels={({ datum }) => Math.round(datum.min)} + */ + minLabels?: VictoryBoxPlotLabelType; + /** + * The name prop is used to reference a component instance when defining shared events. + */ + name?: string; + /** + * Victory components will pass an origin prop is to define the center point in svg coordinates for polar charts. + * + * Note: It will not typically be necessary to set an origin prop manually + * + * @propType { x: number, y: number } + */ + origin?: OriginType; + /** + * The padding props specifies the amount of padding in number of pixels between + * the edge of the chart and any rendered child components. This prop can be given + * as a number or as an object with padding specified for top, bottom, left + * and right. + * + * @propType number | { top: number, bottom: number, left: number, right: number } + */ + padding?: PaddingProps; + /** + * Victory components can pass a boolean polar prop to specify whether a label is part of a polar chart. + * + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + polar?: boolean; + /** + * Use the q1 data accessor prop to define the q1 value of a box plot. + * + * @propType string | array[string] | function + * @example Specify which property in an array of data objects should be used as the q1 value + * + * q1="q1_value" + * + * @example Use a function to translate each element in a data array into a q1 value + * + * q1={() => 10} + * + * @example Specify which property in an array of nested data objects should be used as a q1 value + * + * q1="bonds.q1", q1={["bonds", "q1"]} + */ + q1?: StringOrNumberOrCallback | string[]; + /** + * The q1Component prop takes a component instance which will be responsible for rendering an element to represent the + * q1 value of the box plot. The new element created from the passed q1Component will be provided with the following + * props calculated by ChartBoxPlot: datum, index, scale, style, events, x, y, width and height Any of these props + * may be overridden by passing in props to the supplied component, or modified or ignored within the custom component + * itself. If a q1Component is not provided, ChartBoxPlot will use its default Box component. + */ + q1Component?: React.ReactElement; + /** + * The q1LabelComponent prop takes a component instance which will be used to render the label corresponding to the q1 + * value for each box. The new element created from the passed q1LabelComponent will be supplied with the following + * props: x, y, datum, index, scale, verticalAnchor, textAnchor, angle, transform, style and events. Any of these + * props may be overridden by passing in props to the supplied component, or modified or ignored within the custom + * component itself. If q1LabelComponent is omitted, a new ChartLabel will be created with props described above. + */ + q1LabelComponent?: React.ReactElement; + /** + * The q1Labels prop defines the labels that will appear above each point. This prop should be given as a boolean, an + * array or as a function of the props corresponding to that label. When given as a boolean value, the q1 value of + * each datum will be used for the label. + * + * @propType string | function | boolean + * @example + * + * q1Labels={["first", "second", "third"]} + * q1Labels={({ datum }) => Math.round(datum.q1)} + */ + q1Labels?: VictoryBoxPlotLabelType; + /** + * Use the q3 data accessor prop to define the q3 value of a box plot. + * + * @propType string | array[string] | function + * @example Specify which property in an array of data objects should be used as the q3 value + * + * q3="q3_value" + * + * @example Use a function to translate each element in a data array into a q3 value + * + * q3={() => 10} + * + * @example Specify which property in an array of nested data objects should be used as a q3 value + * + * q3="bonds.q3", q3={["bonds", "q3"]} + */ + q3?: StringOrNumberOrCallback | string[]; + /** + * The q3Component prop takes a component instance which will be responsible for rendering an element to represent the + * q3 value of the box plot. The new element created from the passed q3Component will be provided with the following + * props calculated by ChartBoxPlot: datum, index, scale, style, events, x, y, width and height Any of these props + * may be overridden by passing in props to the supplied component, or modified or ignored within the custom component + * itself. If a q3Component is not provided, ChartBoxPlot will use its default Box component. + */ + q3Component?: React.ReactElement; + /** + * The q3LabelComponent prop takes a component instance which will be used to render the label corresponding to the q3 + * value for each box. The new element created from the passed q3LabelComponent will be supplied with the following + * props: x, y, datum, index, scale, verticalAnchor, textAnchor, angle, transform, style and events. Any of these + * props may be overridden by passing in props to the supplied component, or modified or ignored within the custom + * component itself. If q3LabelComponent is omitted, a new ChartLabel will be created with props described above. + */ + q3LabelComponent?: React.ReactElement; + /** + * The q3Labels prop defines the labels that will appear above each point. This prop should be given as a boolean, an + * array or as a function of the props corresponding to that label. When given as a boolean value, the q3 value of + * each datum will be used for the label. + * + * @propType string | function | boolean + * @example + * + * q3Labels={["first", "second", "third"]} + * q3Labels={({ datum }) => Math.round(datum.q3)} + */ + q3Labels?: VictoryBoxPlotLabelType; + /** + * The range prop describes the dimensions over which data may be plotted. For cartesian coordinate systems, this + * corresponds to minimum and maximum svg coordinates in the x and y dimension. In polar coordinate systems this + * corresponds to a range of angles and radii. When this value is not given it will be calculated from the width, + * height, and padding, or from the startAngle and endAngle in the case of polar charts. All components in a given + * chart must share the same range, so setting this prop on children nested within Chart or + * ChartGroup will have no effect. This prop is usually not set manually. + * + * @propType number[] | { x: number[], y: number[] } + * @example [low, high] | { x: [low, high], y: [low, high] } + * + * Cartesian: range={{ x: [50, 250], y: [50, 250] }} + * Polar: range={{ x: [0, 360], y: [0, 250] }} + */ + range?: RangePropType; + /** + * The samples prop specifies how many individual points to plot when plotting + * y as a function of x. Samples is ignored if x props are provided instead. + */ + samples?: number; + /** + * The scale prop determines which scales your chart should use. This prop can be + * given as a string specifying a supported scale ("linear", "time", "log", "sqrt"), + * as a d3 scale function, or as an object with scales specified for x and y + * + * @propType string | { x: string, y: string } + * @example d3Scale.time(), {x: "linear", y: "log"} + */ + scale?: + | ScalePropType + | D3Scale + | { + x?: ScalePropType | D3Scale; + y?: ScalePropType | D3Scale; + }; + /** + * The sharedEvents prop is used internally to coordinate events between components. + * + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + sharedEvents?: { events: any[]; getEventState: Function }; + /** + * By default domainPadding is coerced to existing quadrants. This means that if a given domain only includes positive + * values, no amount of padding applied by domainPadding will result in a domain with negative values. This is the + * desired behavior in most cases. For users that need to apply padding without regard to quadrant, the + * singleQuadrantDomainPadding prop may be used. This prop may be given as a boolean or an object with boolean values + * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied + * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. + * + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable + * will corresponds to the y axis. + * + * @example + * + * singleQuadrantDomainPadding={false} + * singleQuadrantDomainPadding={{ x: false }} + */ + singleQuadrantDomainPadding?: boolean | { x?: boolean; y?: boolean }; + /** + * Use the sortKey prop to indicate how data should be sorted. This prop + * is given directly to the lodash sortBy function to be executed on the + * final dataset. + * + * @propType number | string | Function | string[] + */ + sortKey?: DataGetterPropType; + /** + * The sortOrder prop specifies whether sorted data should be returned in 'ascending' or 'descending' order. + * + * @propType string + */ + sortOrder?: SortOrderPropType; + /** + * The standalone prop determines whether the component will render a standalone svg + * or a tag that will be included in an external svg. Set standalone to false to + * compose ChartBoxPlot with other components within an enclosing tag. + */ + standalone?: boolean; + /** + * The style prop specifies styles for your ChartBoxPlot. Any valid inline style properties + * will be applied. Height, width, and padding should be specified via the height, + * width, and padding props, as they are used to calculate the alignment of + * components within chart. + * + * @propType { parent: object, data: object, labels: object } + * @example {data: {fill: "red"}, labels: {fontSize: 12}} + */ + style?: VictoryStyleInterface; + /** + * The theme prop takes a style object with nested data, labels, and parent objects. + * You can create this object yourself, or you can use a theme provided by + * When using ChartBoxPlot as a solo component, implement the theme directly on + * ChartBoxPlot. If you are wrapping ChartBoxPlot in ChartChart or ChartGroup, + * please call the theme on the outermost wrapper component instead. + * + * @propType object + */ + theme?: ChartThemeDefinition; + /** + * Specifies the theme color. Valid values are 'blue', 'green', 'multi', etc. + * + * Note: Not compatible with theme prop + * + * @example themeColor={ChartThemeColor.blue} + */ + themeColor?: string; + /** + * The whiskerWidth prop specifies how wide each whisker crosshair should be. If the whiskerWidth prop is not set, the + * width of the whisker crosshair will match the width of the box. + */ + whiskerWidth?: number; + /** + * The width props specifies the width of the svg viewBox of the chart container + * This value should be given as a number of pixels + */ + width?: number; + /** + * The x prop specifies how to access the X value of each data point. + * If given as a function, it will be run on each data point, and returned value will be used. + * If given as an integer, it will be used as an array index for array-type data points. + * If given as a string, it will be used as a property key for object-type data points. + * If given as an array of strings, or a string containing dots or brackets, + * it will be used as a nested object property path (for details see Lodash docs for _.get). + * If `null` or `undefined`, the data value will be used as is (identity function/pass-through). + * + * @propType number | string | Function | string[] + * @example 0, 'x', 'x.value.nested.1.thing', 'x[2].also.nested', null, d => Math.sin(d) + */ + x?: DataGetterPropType; + /** + * The y prop specifies how to access the Y value of each data point. + * If given as a function, it will be run on each data point, and returned value will be used. + * If given as an integer, it will be used as an array index for array-type data points. + * If given as a string, it will be used as a property key for object-type data points. + * If given as an array of strings, or a string containing dots or brackets, + * it will be used as a nested object property path (for details see Lodash docs for _.get). + * If `null` or `undefined`, the data value will be used as is (identity function/pass-through). + * + * @propType number | string | Function | string[] + * @example 0, 'y', 'y.value.nested.1.thing', 'y[2].also.nested', null, d => Math.sin(d) + */ + y?: DataGetterPropType; + /** + * Use y0 data accessor prop to determine how the component defines the baseline y0 data. + * This prop is useful for defining custom baselines for components like ChartBoxPlot. + * This prop may be given in a variety of formats. + * + * @propType number | string | Function | string[] + * @example 'last_quarter_profit', () => 10, 1, 'employees.salary', ["employees", "salary"] + */ + y0?: DataGetterPropType; +} + +export const ChartBoxPlot: React.FunctionComponent = ({ + containerComponent = , + themeColor, + + // destructure last + theme = getTheme(themeColor), + ...rest +}: ChartBoxPlotProps) => { + // Clone so users can override container props + const container = cloneElement(containerComponent, { + theme, + ...containerComponent.props + }); + + // Note: containerComponent is required for theme + return ; +}; +ChartBoxPlot.displayName = 'ChartBoxPlot'; + +// Note: VictoryBar.getDomain & VictoryBar.role must be hoisted +hoistNonReactStatics(ChartBoxPlot, VictoryBoxPlot); diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/__snapshots__/ChartBoxPlot.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBoxPlot/__snapshots__/ChartBoxPlot.test.tsx.snap new file mode 100644 index 00000000000..1b3012183fa --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/__snapshots__/ChartBoxPlot.test.tsx.snap @@ -0,0 +1,996 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBar 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +`; + +exports[`ChartBar 2`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2015 + + + + + + + + 2016 + + + + + + + + 2017 + + + + + + + + 2018 + + + + + + + + + + + 2 + + + + + + + + 4 + + + + + + + + 6 + + + + + + + + 8 + + + + + + + + 10 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlot.md b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlot.md new file mode 100644 index 00000000000..cccdad20c88 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlot.md @@ -0,0 +1,69 @@ +--- +id: Box plot chart +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartAxis', + 'ChartBoxPlot', + 'ChartCursorFlyout', + 'ChartCursorTooltip', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { Chart, ChartAxis, ChartBoxPlot, ChartCursorFlyout, ChartCursorTooltip, ChartLegendTooltip, ChartThemeColor, ChartThreshold, ChartVoronoiContainer, createContainer } from '@patternfly/react-charts/victory'; +import { VictoryZoomContainer } from 'victory-zoom-container'; +import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + + +## Examples +### Basic with right aligned legend +```ts file = "ChartBoxPlotRightAlignedLegend.tsx" + +``` + +### Labels with bottom aligned legend + +This demonstrates how to display labels. + +```ts file= "ChartBoxPlotLabelsLegend.tsx" + +``` + +### Embedded legend + +This demonstrates how to embed a legend within a tooltip. Combining cursor and voronoi containers is required to display tooltips with a vertical cursor. + +```ts file = "ChartBoxPlotEmbeddedLegend.tsx" + +``` + +### Embedded HTML + +This demonstrates how to embed HTML within a tooltip. Combining cursor and voronoi containers is required to display tooltips with a vertical cursor. + +```ts file = "ChartBoxPlotEmbeddedHtml.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- The `theme` and `themeColor` props should be applied at the most top level component + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBoxPlot` props, see [VictoryBoxPlot](https://formidable.com/open-source/victory/docs/victory-box-plot) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotEmbeddedHtml.tsx b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotEmbeddedHtml.tsx new file mode 100644 index 00000000000..edf1e21b724 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotEmbeddedHtml.tsx @@ -0,0 +1,125 @@ +import { + Chart, + ChartAxis, + ChartBoxPlot, + ChartCursorTooltip, + ChartThemeColor, + createContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number[] | number; +} + +export const ChartBoxPlotEmbeddedHtml: React.FunctionComponent = () => { + const baseStyles = { + color: '#f0f0f0', + fontFamily: + '"Red Hat Text", "RedHatText", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans JP", "Noto Sans KR", "Noto Sans Malayalam", "Noto Sans SC", "Noto Sans TC", "Noto Sans Thai", Helvetica, Arial, sans-serif', + fontSize: '14px' + }; + const leftColumn = { + paddingLeft: '10px', + width: '50%' + }; + const rightColumn = { + paddingRight: '20px', + textAlign: 'right', + width: '50%' + }; + + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: [1, 2, 3, 5] }, + { name: 'Cats', x: '2016', y: [3, 2, 8, 10] }, + { name: 'Cats', x: '2017', y: [2, 8, 6, 5] }, + { name: 'Cats', x: '2018', y: [1, 3, 2, 9] } + ]; + const legendData = [{ name: 'Cats' }]; + + // Custom HTML component to create a legend layout + const HtmlLegendContent = ({ datum, _text, title, x, y, ..._rest }) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + {title(datum)} +
    Max{datum._max}
    Median{datum._median}
    Min{datum._min}
    Q1{datum._q1}
    Q3{datum._q3}
    +
    +
    + ); + + return ( +
    + `${datum.y}`} + labelComponent={ + datum.x} />} + /> + } + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + domain={{ y: [0, 12] }} + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendPosition="bottom" + height={300} + name="chart4" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.orange} + width={600} + > + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotEmbeddedLegend.tsx b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotEmbeddedLegend.tsx new file mode 100644 index 00000000000..fd06bf7064d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotEmbeddedLegend.tsx @@ -0,0 +1,106 @@ +import { + Chart, + ChartAxis, + ChartBoxPlot, + ChartLegendTooltip, + ChartThemeColor, + ChartThreshold, + createContainer +} from '@patternfly/react-charts/victory'; +import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; + +interface Data { + name: string; + x: string; + y: number[] | number; +} + +export const ChartBoxPlotEmbeddedLegend: React.FunctionComponent = () => { + const catsData: Data[] = [ + { name: 'Cats', x: '2015', y: [null] }, + { name: 'Cats', x: '2016', y: [3, 2, 8, 10] }, + { name: 'Cats', x: '2017', y: [2, 8, 6, 5] }, + { name: 'Cats', x: '2018', y: [1, 3, 2, 9] } + ]; + + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const limitData: Data[] = [ + { name: 'Limit', x: '2015', y: 12 }, + { name: 'Limit', x: '2016', y: 12 }, + { name: 'Limit', x: '2017', y: 12 }, + { name: 'Limit', x: '2018', y: 12 } + ]; + const legendData = [ + { + childName: 'limit', + name: 'Limit', + symbol: { fill: chart_color_orange_300.var, type: 'threshold' } + }, + { childName: 'cats', name: 'Cats' }, + // Force extra space below for line wrapping + { + childName: 'cats', + name: '', + symbol: { fill: 'none' } + }, + { + childName: 'cats', + name: '', + symbol: { fill: 'none' } + } + ]; + const labelFormatter = (datum) => { + // With box plot data, datum.y will also be an array + if (datum && (datum._min || datum._median || datum._max || datum._q1 || datum._q3)) { + return `Min: ${datum._min}, Max: ${datum._max}\nMedian: ${datum._median}\nQ1: ${datum._q1}, Q3: ${datum._q3}`; + } + const yVal = Array.isArray(datum.y) ? datum.y[0] : datum.y; + return yVal !== null ? yVal : 'no data'; + }; + return ( +
    + labelFormatter(datum)} + labelComponent={ datum.x} />} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + domain={{ y: [0, 13] }} + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendPosition="bottom" + height={350} + name="chart5" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.green} + width={600} + > + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotLabelsLegend.tsx b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotLabelsLegend.tsx new file mode 100644 index 00000000000..fc34a6e6104 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotLabelsLegend.tsx @@ -0,0 +1,51 @@ +import { Chart, ChartAxis, ChartBoxPlot, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number[]; +} + +export const ChartBoxPlotLabelsLegend: React.FunctionComponent = () => { + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: [1, 2, 3, 5] }, + { name: 'Cats', x: '2016', y: [3, 2, 8, 10] }, + { name: 'Cats', x: '2017', y: [2, 8, 6, 5] }, + { name: 'Cats', x: '2018', y: [1, 3, 2, 9] } + ]; + const legendData = [{ name: 'Cats' }]; + return ( +
    + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotRightAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotRightAlignedLegend.tsx new file mode 100644 index 00000000000..87a8a98b9ef --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBoxPlot/examples/ChartBoxPlotRightAlignedLegend.tsx @@ -0,0 +1,45 @@ +import { Chart, ChartAxis, ChartBoxPlot, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number[]; +} + +export const ChartBoxPlotRightAlignedLegend: React.FunctionComponent = () => { + const catsData: PetData[] = [ + { name: 'Cats', x: '2015', y: [1, 2, 3, 5] }, + { name: 'Cats', x: '2016', y: [3, 2, 8, 10] }, + { name: 'Cats', x: '2017', y: [2, 8, 6, 5] }, + { name: 'Cats', x: '2018', y: [1, 3, 2, 9] } + ]; + + const legendData = [{ name: 'Cats' }]; + return ( +
    + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBullet.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBullet.test.tsx new file mode 100644 index 00000000000..d46d659c501 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBullet.test.tsx @@ -0,0 +1,33 @@ +import { render } from '@testing-library/react'; +import { ChartAxis } from '../ChartAxis/ChartAxis'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartBullet } from './ChartBullet'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletQualitativeRange', () => { + const { asFragment } = render( + } />} /> + ); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + primarySegmentedMeasureData={[{ name: 'Measure', y: 50 }]} + qualitativeRangeData={[ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]} + width={450} + axisComponent={} />} + /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBullet.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBullet.tsx similarity index 83% rename from packages/react-charts/src/components/ChartBullet/ChartBullet.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBullet.tsx index 78f708d1578..dc146b522b9 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBullet.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBullet.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement, Fragment, useEffect } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { DataGetterPropType, DomainPropType, PaddingProps } from 'victory-core'; import { VictoryChart } from 'victory-chart'; @@ -10,9 +10,14 @@ import { getPrimarySegmentedMeasureWidth, getQualitativeRangeBarWidth } from './utils/chart-bullet-size'; -import { getBulletDomain } from './utils/chart-bullet-domain'; -import { getBulletThemeWithLegendColorScale } from './utils/chart-bullet-theme'; -import { ChartAxis } from '../ChartAxis'; +import { ChartAxis } from '../ChartAxis/ChartAxis'; +import { ChartBulletTitle } from './ChartBulletTitle'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLegend } from '../ChartLegend/ChartLegend'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; +import { ChartBulletStyles } from '../ChartTheme/ChartStyles'; +import { getComputedLegend, getLegendItemsExtraHeight, getLegendMaxTextWidth } from '../ChartUtils/chart-legend'; import { ChartBulletComparativeErrorMeasure } from './ChartBulletComparativeErrorMeasure'; import { ChartBulletComparativeMeasure } from './ChartBulletComparativeMeasure'; import { ChartBulletComparativeWarningMeasure } from './ChartBulletComparativeWarningMeasure'; @@ -20,16 +25,16 @@ import { ChartBulletGroupTitle } from './ChartBulletGroupTitle'; import { ChartBulletPrimaryDotMeasure } from './ChartBulletPrimaryDotMeasure'; import { ChartBulletPrimarySegmentedMeasure } from './ChartBulletPrimarySegmentedMeasure'; import { ChartBulletQualitativeRange } from './ChartBulletQualitativeRange'; -import { ChartBulletTitle } from './ChartBulletTitle'; -import { ChartContainer } from '../ChartContainer'; -import { ChartLegend, ChartLegendOrientation, ChartLegendPosition } from '../ChartLegend'; -import { ChartBulletStyles, ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; -import { getComputedLegend, getPaddingForSide } from '../ChartUtils'; +import { getBulletDomain } from './utils/chart-bullet-domain'; +import { getBulletThemeWithLegendColorScale } from './utils/chart-bullet-theme'; +import { getPaddingForSide } from '../ChartUtils/chart-padding'; +import { ChartPoint } from '../ChartPoint/ChartPoint'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-chart/src/index.d.ts + * ChartBullet renders a dataset as a bullet chart. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-chart/src/victory-chart.tsx */ export interface ChartBulletProps { /** @@ -206,12 +211,20 @@ export interface ChartBulletProps { */ labels?: string[] | number[] | ((data: any) => string | number | null); /** - * Allows legend items to wrap. A value of true allows the legend to wrap onto the next line - * if its container is not wide enough. + * Allows legend items to wrap onto the next line if the chart is not wide enough. + * + * Note that the chart's SVG height and width are 100% by default, so it can be responsive itself. However, if you + * define the height and width of the chart's parent container, you must accommodate for extra legend height due to + * legend items wrapping onto the next line. When the height of the chart's parent container is too small, some legend + * items may not be visible. + * + * Alternatively, a callback function may be provided, which will be called after the legend's itemsPerRow property + * has been calculated. The value provided can be used to increase the chart's parent container height as legend + * items wrap onto the next line. If no adjustment is necessary, the value will be zero. * * Note: This is overridden by the legendItemsPerRow property */ - legendAllowWrap?: boolean; + legendAllowWrap?: boolean | ((extraHeight: number) => void); /** * The legend component to render with chart. */ @@ -240,12 +253,16 @@ export interface ChartBulletProps { * cases, the legend may not be visible until enough padding is applied. */ legendPosition?: 'bottom' | 'bottom-left' | 'right'; + /** + * Text direction of the legend labels. + */ + legendDirection?: 'ltr' | 'rtl'; /** * The maxDomain prop defines a maximum domain value for a chart. This prop is useful in situations where the maximum * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -262,7 +279,7 @@ export interface ChartBulletProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -274,6 +291,12 @@ export interface ChartBulletProps { * Note: The x domain is expected to be `x: 0` in order to position all measures properly */ minDomain?: number | { x?: number; y?: number }; + /** + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. + */ + name?: string; /** * The padding props specifies the amount of padding in number of pixels between * the edge of the chart and any rendered child components. This prop can be given @@ -440,14 +463,6 @@ export interface ChartBulletProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title for the chart */ @@ -498,9 +513,11 @@ export const ChartBullet: React.FunctionComponent = ({ legendAllowWrap = false, legendComponent = , legendItemsPerRow, - legendPosition = 'bottom' as ChartLegendPosition, + legendPosition = 'bottom', + legendDirection = 'ltr', maxDomain, minDomain, + name, padding, primaryDotMeasureComponent = , primaryDotMeasureData, @@ -518,7 +535,6 @@ export const ChartBullet: React.FunctionComponent = ({ standalone = true, subTitle, themeColor, - themeVariant, title, titleComponent = , titlePosition, @@ -536,8 +552,7 @@ export const ChartBullet: React.FunctionComponent = ({ primarySegmentedMeasureLegendData, qualitativeRangeData, qualitativeRangeLegendData, - themeColor, - themeVariant + themeColor }), domain = getBulletDomain({ comparativeErrorMeasureComponent, @@ -553,7 +568,7 @@ export const ChartBullet: React.FunctionComponent = ({ qualitativeRangeComponent, qualitativeRangeData }), - legendOrientation = theme.legend.orientation as ChartLegendOrientation, + legendOrientation = theme.legend.orientation as any, height = horizontal ? theme.chart.height : theme.chart.width, width = horizontal ? theme.chart.width : theme.chart.height, bulletSize = theme.chart.height @@ -572,24 +587,28 @@ export const ChartBullet: React.FunctionComponent = ({ }; // Bullet group title - const bulletGroupTitle = React.cloneElement(groupTitleComponent, { + const bulletGroupTitle = cloneElement(groupTitleComponent, { height, + ...(name && { name: `${name}-${(groupTitleComponent as any).type.displayName}` }), standalone: false, subTitle: groupSubTitle, title: groupTitle, + themeColor, width, ...groupTitleComponent.props }); // Bullet title - const bulletTitle = React.cloneElement(titleComponent, { + const bulletTitle = cloneElement(titleComponent, { height, horizontal, legendPosition, + ...(name && { name: `${name}-${(titleComponent as any).type.displayName}` }), padding, standalone: false, subTitle, theme, + themeColor, title, titlePosition, width, @@ -597,9 +616,14 @@ export const ChartBullet: React.FunctionComponent = ({ }); // Comparative error measure - const comparativeErrorMeasure = React.cloneElement(comparativeErrorMeasureComponent, { + const comparativeErrorMeasure = cloneElement(comparativeErrorMeasureComponent, { allowTooltip, - barWidth: getComparativeMeasureErrorWidth({ height: chartSize.height, horizontal, width: chartSize.width }), + barWidth: getComparativeMeasureErrorWidth({ + height: chartSize.height, + horizontal, + themeColor, + width: chartSize.width + }), constrainToVisibleArea, data: comparativeErrorMeasureData, domain, @@ -609,15 +633,21 @@ export const ChartBullet: React.FunctionComponent = ({ labels, padding, standalone: false, + themeColor, width: chartSize.width, y: comparativeErrorMeasureDataY, ...comparativeErrorMeasureComponent.props }); // Comparative warning measure - const comparativeWarningMeasure = React.cloneElement(comparativeWarningMeasureComponent, { + const comparativeWarningMeasure = cloneElement(comparativeWarningMeasureComponent, { allowTooltip, - barWidth: getComparativeMeasureWarningWidth({ height: chartSize.height, horizontal, width: chartSize.width }), + barWidth: getComparativeMeasureWarningWidth({ + height: chartSize.height, + horizontal, + themeColor, + width: chartSize.width + }), constrainToVisibleArea, data: comparativeWarningMeasureData, domain, @@ -627,26 +657,42 @@ export const ChartBullet: React.FunctionComponent = ({ labels, padding, standalone: false, + themeColor, width: chartSize.width, y: comparativeWarningMeasureDataY, ...comparativeWarningMeasureComponent.props }); // Comparative zero measure - const comparativeZeroMeasure = React.cloneElement(comparativeZeroMeasureComponent, { - barWidth: getComparativeMeasureWidth({ height: chartSize.height, horizontal, width: chartSize.width }), + const comparativeZeroMeasure = cloneElement(comparativeZeroMeasureComponent, { + barWidth: getComparativeMeasureWidth({ height: chartSize.height, horizontal, themeColor, width: chartSize.width }), data: [{ y: 0 }], domain, height: chartSize.height, horizontal, padding, standalone: false, + themeColor, width: chartSize.width, ...comparativeZeroMeasureComponent.props }); + let legendXOffset = 0; + if (legendDirection === 'rtl') { + legendXOffset = getLegendMaxTextWidth( + [ + ...(primaryDotMeasureLegendData ? primaryDotMeasureLegendData : []), + ...(primarySegmentedMeasureLegendData ? primarySegmentedMeasureLegendData : []), + ...(comparativeWarningMeasureLegendData ? comparativeWarningMeasureLegendData : []), + ...(comparativeErrorMeasureLegendData ? comparativeErrorMeasureLegendData : []), + ...(qualitativeRangeLegendData ? qualitativeRangeLegendData : []) + ], + theme + ); + } + // Legend - const legend = React.cloneElement(legendComponent, { + const legend = cloneElement(legendComponent, { data: [ ...(primaryDotMeasureLegendData ? primaryDotMeasureLegendData : []), ...(primarySegmentedMeasureLegendData ? primarySegmentedMeasureLegendData : []), @@ -654,15 +700,34 @@ export const ChartBullet: React.FunctionComponent = ({ ...(comparativeErrorMeasureLegendData ? comparativeErrorMeasureLegendData : []), ...(qualitativeRangeLegendData ? qualitativeRangeLegendData : []) ], + ...(name && { name: `${name}-${(legendComponent as any).type.displayName}` }), itemsPerRow: legendItemsPerRow, orientation: legendOrientation, position: legendPosition, theme, + themeColor, + ...(legendDirection === 'rtl' && { + dataComponent: legendComponent.props.dataComponent ? ( + cloneElement(legendComponent.props.dataComponent, { transform: `translate(${legendXOffset})` }) + ) : ( + + ) + }), + ...(legendDirection === 'rtl' && { + labelComponent: legendComponent.props.labelComponent ? ( + cloneElement(legendComponent.props.labelComponent, { + direction: 'rtl', + dx: legendXOffset - 30 + }) + ) : ( + + ) + }), ...legendComponent.props }); // Primary dot measure - const primaryDotMeasure = React.cloneElement(primaryDotMeasureComponent, { + const primaryDotMeasure = cloneElement(primaryDotMeasureComponent, { allowTooltip, constrainToVisibleArea, data: primaryDotMeasureData, @@ -673,20 +738,24 @@ export const ChartBullet: React.FunctionComponent = ({ labelComponent: allowTooltip ? : undefined, labels, padding, - size: getPrimaryDotMeasureSize({ height: chartSize.height, horizontal, width: chartSize.width }), + size: getPrimaryDotMeasureSize({ height: chartSize.height, horizontal, themeColor, width: chartSize.width }), standalone: false, themeColor, - themeVariant, width: chartSize.width, y: primaryDotMeasureDataY, ...primaryDotMeasureComponent.props }); // Primary segmented measure - const primarySegmentedMeasure = React.cloneElement(primarySegmentedMeasureComponent, { + const primarySegmentedMeasure = cloneElement(primarySegmentedMeasureComponent, { allowTooltip, constrainToVisibleArea, - barWidth: getPrimarySegmentedMeasureWidth({ height: chartSize.height, horizontal, width: chartSize.width }), + barWidth: getPrimarySegmentedMeasureWidth({ + height: chartSize.height, + horizontal, + themeColor, + width: chartSize.width + }), data: primarySegmentedMeasureData, domain, height: chartSize.height, @@ -697,17 +766,16 @@ export const ChartBullet: React.FunctionComponent = ({ padding, standalone: false, themeColor, - themeVariant, width: chartSize.width, y: primarySegmentedMeasureDataY, ...primarySegmentedMeasureComponent.props }); // Qualitative range - const qualitativeRange = React.cloneElement(qualitativeRangeComponent, { + const qualitativeRange = cloneElement(qualitativeRangeComponent, { allowTooltip, constrainToVisibleArea, - barWidth: getQualitativeRangeBarWidth({ height: chartSize.height, horizontal, width: chartSize.width }), + barWidth: getQualitativeRangeBarWidth({ height: chartSize.height, horizontal, themeColor, width: chartSize.width }), data: qualitativeRangeData, domain, height: chartSize.height, @@ -717,6 +785,7 @@ export const ChartBullet: React.FunctionComponent = ({ labels, padding, standalone: false, + themeColor, width: chartSize.width, y: qualitativeRangeDataY, y0: qualitativeRangeDataY0, @@ -751,7 +820,7 @@ export const ChartBullet: React.FunctionComponent = ({ let dy = 0; // Adjust for padding - if (legendPosition === ChartLegendPosition.bottom) { + if (legendPosition === 'bottom') { if (horizontal) { dy = defaultPadding.top * 0.5 + (defaultPadding.bottom * 0.5 - defaultPadding.bottom) - 25; } else if (title) { @@ -759,7 +828,7 @@ export const ChartBullet: React.FunctionComponent = ({ } else { dy = -defaultPadding.bottom; } - } else if (legendPosition === ChartLegendPosition.bottomLeft) { + } else if (legendPosition === 'bottom-left') { if (horizontal) { dy = defaultPadding.top * 0.5 + (defaultPadding.bottom * 0.5 - defaultPadding.bottom) - 25; } else if (title) { @@ -769,8 +838,9 @@ export const ChartBullet: React.FunctionComponent = ({ } dx = -10; } + return getComputedLegend({ - allowWrap: legendAllowWrap, + allowWrap: legendAllowWrap === true || typeof legendAllowWrap === 'function', chartType: 'bullet', dx, dy, @@ -807,7 +877,7 @@ export const ChartBullet: React.FunctionComponent = ({ }; // Axis component for custom tick values - const axis = React.cloneElement(axisComponent, { + const axis = cloneElement(axisComponent, { dependentAxis: horizontal ? false : true, domain: !horizontal ? domain @@ -816,19 +886,22 @@ export const ChartBullet: React.FunctionComponent = ({ y: (domain as any).x }, height: chartSize.height, + ...(name && { name: `${name}-${(axisComponent as any).type.displayName}` }), // Adjust for padding offsetX: !horizontal ? defaultPadding.left * 0.5 + (defaultPadding.right * 0.5 - (defaultPadding.right - 55)) : 0, offsetY: horizontal ? 80 - defaultPadding.top * 0.5 + (defaultPadding.bottom * 0.5 - 25) : 0, padding, standalone: false, + themeColor, tickCount: ChartBulletStyles.axisTickCount, tickValues: getTickValues((domain as any).y[0], (domain as any).y[1]), width: chartSize.width, ...axisComponent.props }); + const computedLegend = getLegend(); const bulletChart = ( - + {axis} {bulletGroupTitle} {bulletTitle} @@ -838,16 +911,29 @@ export const ChartBullet: React.FunctionComponent = ({ {comparativeErrorMeasure} {comparativeWarningMeasure} {getComparativeZeroMeasure()} - {getLegend()} - + {computedLegend} + ); + // Callback to compliment legendAllowWrap + useEffect(() => { + if (typeof legendAllowWrap === 'function') { + const extraHeight = getLegendItemsExtraHeight({ + legendData: computedLegend.props.data, + legendOrientation: computedLegend.props.orientation, + legendProps: computedLegend.props, + theme + }); + legendAllowWrap(extraHeight); + } + }, [computedLegend, legendAllowWrap, theme, width]); + return standalone ? ( {bulletChart} ) : ( - {bulletChart} + {bulletChart} ); }; ChartBullet.displayName = 'ChartBullet'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeErrorMeasure.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeErrorMeasure.test.tsx new file mode 100644 index 00000000000..0888ac5c552 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeErrorMeasure.test.tsx @@ -0,0 +1,16 @@ +import { render } from '@testing-library/react'; +import { ChartBulletComparativeErrorMeasure } from './ChartBulletComparativeErrorMeasure'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletComparativeErrorMeasure', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx similarity index 91% rename from packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx index e700dc46afd..60ad1770418 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx @@ -1,15 +1,16 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { DataGetterPropType, DomainPropType, NumberOrCallback, PaddingProps } from 'victory-core'; import { VictoryBar } from 'victory-bar'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getBulletComparativeErrorMeasureTheme } from '../ChartUtils'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getBulletComparativeErrorMeasureTheme } from '../ChartUtils/chart-theme-types'; import { ChartBulletComparativeMeasure } from './ChartBulletComparativeMeasure'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-bar/src/index.d.ts + * ChartBulletComparativeErrorMeasure renders a dataset as a comparative error measure. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-bar/src/index.d.ts */ export interface ChartBulletComparativeErrorMeasureProps { /** @@ -142,14 +143,6 @@ export interface ChartBulletComparativeErrorMeasureProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -185,16 +178,15 @@ export const ChartBulletComparativeErrorMeasure: React.FunctionComponent { // Comparative measure component - const measure = React.cloneElement(measureComponent, { + const measure = cloneElement(measureComponent, { allowTooltip, ariaDesc, ariaTitle, @@ -209,6 +201,7 @@ export const ChartBulletComparativeErrorMeasure: React.FunctionComponent ) : ( - {measure} + {measure} ); }; ChartBulletComparativeErrorMeasure.displayName = 'ChartBulletComparativeErrorMeasure'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeMeasure.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeMeasure.test.tsx new file mode 100644 index 00000000000..e26dfffb9da --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeMeasure.test.tsx @@ -0,0 +1,16 @@ +import { render } from '@testing-library/react'; +import { ChartBulletComparativeMeasure } from './ChartBulletComparativeMeasure'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletComparativeMeasure', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeMeasure.tsx similarity index 90% rename from packages/react-charts/src/components/ChartBullet/ChartBulletComparativeMeasure.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeMeasure.tsx index e1a077adff0..0ef3a57b904 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeMeasure.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeMeasure.tsx @@ -1,17 +1,19 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { DataGetterPropType, DomainPropType, NumberOrCallback, PaddingProps } from 'victory-core'; import { VictoryBar } from 'victory-bar'; -import { getComparativeMeasureData } from './utils'; -import { ChartBar } from '../ChartBar'; -import { ChartContainer } from '../ChartContainer'; -import { ChartBulletStyles, ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; -import { getBulletComparativeMeasureTheme } from '../ChartUtils'; +import { getComparativeMeasureData } from './utils/chart-bullet-data'; +import { ChartBar } from '../ChartBar/ChartBar'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartBulletStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; +import { getBulletComparativeMeasureTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-bar/src/index.d.ts + * ChartBulletComparativeMeasure renders a dataset as a comparative measure. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-bar/src/index.d.ts */ export interface ChartBulletComparativeMeasureProps { /** @@ -144,14 +146,6 @@ export interface ChartBulletComparativeMeasureProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -186,11 +180,10 @@ export const ChartBulletComparativeMeasure: React.FunctionComponent @@ -204,7 +197,7 @@ export const ChartBulletComparativeMeasure: React.FunctionComponent { if (horizontal) { @@ -225,7 +218,7 @@ export const ChartBulletComparativeMeasure: React.FunctionComponent - React.cloneElement(measureComponent, { + cloneElement(measureComponent, { barWidth, data: [{ ...dataPoint }], domain, @@ -237,6 +230,7 @@ export const ChartBulletComparativeMeasure: React.FunctionComponent ) : ( - {measure} + {measure} ); }; ChartBulletComparativeMeasure.displayName = 'ChartBulletComparativeMeasure'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeWarningMeasure.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeWarningMeasure.test.tsx new file mode 100644 index 00000000000..83b8fbfde6a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeWarningMeasure.test.tsx @@ -0,0 +1,16 @@ +import { render } from '@testing-library/react'; +import { ChartBulletComparativeWarningMeasure } from './ChartBulletComparativeWarningMeasure'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletComparativeZeroMeasure', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeWarningMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeWarningMeasure.tsx similarity index 91% rename from packages/react-charts/src/components/ChartBullet/ChartBulletComparativeWarningMeasure.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeWarningMeasure.tsx index 1946393d21b..3dc5b08329c 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeWarningMeasure.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletComparativeWarningMeasure.tsx @@ -1,15 +1,16 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { DataGetterPropType, DomainPropType, NumberOrCallback, PaddingProps } from 'victory-core'; import { VictoryBar } from 'victory-bar'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getBulletComparativeWarningMeasureTheme } from '../ChartUtils'; import { ChartBulletComparativeMeasure } from './ChartBulletComparativeMeasure'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getBulletComparativeWarningMeasureTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-bar/src/index.d.ts + * ChartBulletComparativeWarningMeasure renders a dataset as a comparative warning measure. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-bar/src/index.d.ts */ export interface ChartBulletComparativeWarningMeasureProps { /** @@ -142,14 +143,6 @@ export interface ChartBulletComparativeWarningMeasureProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -170,7 +163,9 @@ export interface ChartBulletComparativeWarningMeasureProps { y?: DataGetterPropType; } -export const ChartBulletComparativeWarningMeasure: React.FunctionComponent = ({ +export const ChartBulletComparativeWarningMeasure: React.FunctionComponent< + ChartBulletComparativeWarningMeasureProps +> = ({ allowTooltip = true, ariaDesc, ariaTitle, @@ -185,16 +180,15 @@ export const ChartBulletComparativeWarningMeasure: React.FunctionComponent { // Comparative measure component - const measure = React.cloneElement(measureComponent, { + const measure = cloneElement(measureComponent, { allowTooltip, ariaDesc, ariaTitle, @@ -209,6 +203,7 @@ export const ChartBulletComparativeWarningMeasure: React.FunctionComponent ) : ( - {measure} + {measure} ); }; ChartBulletComparativeWarningMeasure.displayName = 'ChartBulletComparativeWarningMeasure'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletGroupTitle.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletGroupTitle.test.tsx new file mode 100644 index 00000000000..6894adecf04 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletGroupTitle.test.tsx @@ -0,0 +1,17 @@ +import { render } from '@testing-library/react'; +import { ChartBulletGroupTitle } from './ChartBulletGroupTitle'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletGroupTitle', () => { + const { asFragment } = render(} />); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + } /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletGroupTitle.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletGroupTitle.tsx similarity index 81% rename from packages/react-charts/src/components/ChartBullet/ChartBulletGroupTitle.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletGroupTitle.tsx index 13da83dc82f..17a9b1db978 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletGroupTitle.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletGroupTitle.tsx @@ -1,18 +1,16 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import { PaddingProps, Line, StringOrNumberOrCallback } from 'victory-core'; -import { ChartContainer } from '../ChartContainer'; -import { ChartLabel } from '../ChartLabel'; -import { ChartBulletStyles, ChartThemeDefinition } from '../ChartTheme'; -import { - getBulletGroupTitleTheme, - getLabelTextSize, - getBulletLabelX, - getBulletLabelY, - getPaddingForSide -} from '../ChartUtils'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartBulletStyles } from '../ChartTheme/ChartStyles'; +import { getLabelTextSize, getBulletLabelX, getBulletLabelY } from '../ChartUtils/chart-label'; +import { getPaddingForSide } from '../ChartUtils/chart-padding'; +import { getBulletGroupTitleTheme } from '../ChartUtils/chart-theme-types'; +import { getComponentTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts + * ChartBulletGroupTitle renders a group title. */ export interface ChartBulletGroupTitleProps { /** @@ -47,6 +45,12 @@ export interface ChartBulletGroupTitleProps { * This value should be given as a number of pixels */ height?: number; + /** + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. + */ + name?: string; /** * The padding props specifies the amount of padding in number of pixels between * the edge of the chart and any rendered child components. This prop can be given @@ -92,14 +96,6 @@ export interface ChartBulletGroupTitleProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title to render for grouped bullets */ @@ -122,16 +118,16 @@ export const ChartBulletGroupTitle: React.FunctionComponent, + name, padding, standalone = true, subTitle, themeColor, - themeVariant, title, titleComponent = , // destructure last - theme = getBulletGroupTitleTheme(themeColor, themeVariant), + theme = getBulletGroupTitleTheme(themeColor), height = theme.chart.height, width = theme.chart.width }: ChartBulletGroupTitleProps) => { @@ -158,7 +154,7 @@ export const ChartBulletGroupTitle: React.FunctionComponent { + const componentTheme = getComponentTheme(themeColor); const titleProps = titleComponent ? titleComponent.props : {}; const showBoth = title && subTitle; - return React.cloneElement(titleComponent, { + return cloneElement(titleComponent, { ...(showBoth && { capHeight }), + ...(name && { id: () => `${name}-${(titleComponent as any).type.displayName}` }), style: [ChartBulletStyles.label.groupTitle, ChartBulletStyles.label.subTitle], text: showBoth ? [title, subTitle] : title, textAnchor: 'middle', @@ -187,15 +185,16 @@ export const ChartBulletGroupTitle: React.FunctionComponent + {getTitle()} {getDivider()} - + ); return standalone ? ( @@ -203,7 +202,7 @@ export const ChartBulletGroupTitle: React.FunctionComponent ) : ( - {groupTitle} + {groupTitle} ); }; ChartBulletGroupTitle.displayName = 'ChartBulletGroupTitle'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimaryDotMeasure.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimaryDotMeasure.test.tsx new file mode 100644 index 00000000000..42e88fe96a4 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimaryDotMeasure.test.tsx @@ -0,0 +1,16 @@ +import { render } from '@testing-library/react'; +import { ChartBulletPrimaryDotMeasure } from './ChartBulletPrimaryDotMeasure'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletPrimaryDotMeasure', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimaryDotMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimaryDotMeasure.tsx similarity index 90% rename from packages/react-charts/src/components/ChartBullet/ChartBulletPrimaryDotMeasure.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimaryDotMeasure.tsx index 00855dcef21..9ee7e48a6d0 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimaryDotMeasure.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimaryDotMeasure.tsx @@ -1,17 +1,19 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { DataGetterPropType, DomainPropType, PaddingProps } from 'victory-core'; import { VictoryScatter } from 'victory-scatter'; -import { getPrimaryDotMeasureData } from './utils'; -import { ChartContainer } from '../ChartContainer'; -import { ChartScatter } from '../ChartScatter'; -import { ChartBulletStyles, ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; -import { getBulletPrimaryDotMeasureTheme } from '../ChartUtils'; +import { getPrimaryDotMeasureData } from './utils/chart-bullet-data'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartScatter } from '../ChartScatter/ChartScatter'; +import { ChartBulletStyles } from '../ChartTheme/ChartStyles'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; +import { getBulletPrimaryDotMeasureTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-scatter/src/index.d.ts + * ChartBulletPrimaryDotMeasure renders a dataset as the primary dot measure. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-scatter/src/index.d.ts */ export interface ChartBulletPrimaryDotMeasureProps { /** @@ -142,14 +144,6 @@ export interface ChartBulletPrimaryDotMeasureProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -194,12 +188,11 @@ export const ChartBulletPrimaryDotMeasure: React.FunctionComponent, height = theme.group.height, width = theme.group.width @@ -215,7 +208,7 @@ export const ChartBulletPrimaryDotMeasure: React.FunctionComponent - React.cloneElement(measureComponent, { + cloneElement(measureComponent, { data: [{ ...dataPoint }], domain, height, @@ -241,6 +234,7 @@ export const ChartBulletPrimaryDotMeasure: React.FunctionComponent ) : ( - {measure} + {measure} ); }; ChartBulletPrimaryDotMeasure.displayName = 'ChartBulletPrimaryDotMeasure'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.test.tsx new file mode 100644 index 00000000000..f5cef6f4737 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.test.tsx @@ -0,0 +1,16 @@ +import { render } from '@testing-library/react'; +import { ChartBulletPrimarySegmentedMeasure } from './ChartBulletPrimarySegmentedMeasure'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletPrimarySegmentedMeasure', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.tsx similarity index 90% rename from packages/react-charts/src/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.tsx index 0d41e9bccaa..14372952dc8 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletPrimarySegmentedMeasure.tsx @@ -1,17 +1,22 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { DataGetterPropType, DomainPropType, NumberOrCallback, PaddingProps } from 'victory-core'; import { VictoryBar } from 'victory-bar'; -import { getPrimarySegmentedMeasureData } from './utils'; -import { ChartBar } from '../ChartBar'; -import { ChartContainer } from '../ChartContainer'; -import { ChartBulletStyles, ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; -import { getBulletPrimaryNegativeMeasureTheme, getBulletPrimarySegmentedMeasureTheme } from '../ChartUtils'; +import { getPrimarySegmentedMeasureData } from './utils/chart-bullet-data'; +import { ChartBar } from '../ChartBar/ChartBar'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartBulletStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; +import { + getBulletPrimaryNegativeMeasureTheme, + getBulletPrimarySegmentedMeasureTheme +} from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-bar/src/index.d.ts + * ChartBulletPrimarySegmentedMeasure renders a dataset as the primary segmented measure. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-bar/src/index.d.ts */ export interface ChartBulletPrimarySegmentedMeasureProps { /** @@ -158,14 +163,6 @@ export interface ChartBulletPrimarySegmentedMeasureProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -210,13 +207,12 @@ export const ChartBulletPrimarySegmentedMeasure: React.FunctionComponent @@ -233,7 +229,7 @@ export const ChartBulletPrimarySegmentedMeasure: React.FunctionComponent { if (horizontal) { @@ -254,7 +250,7 @@ export const ChartBulletPrimarySegmentedMeasure: React.FunctionComponent - React.cloneElement(measureComponent, { + cloneElement(measureComponent, { barWidth, data: [{ ...dataPoint }], domain, @@ -271,6 +267,7 @@ export const ChartBulletPrimarySegmentedMeasure: React.FunctionComponent ) : ( - {measure} + {measure} ); }; ChartBulletPrimarySegmentedMeasure.displayName = 'ChartBulletPrimarySegmentedMeasure'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletQualitativeRange.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletQualitativeRange.test.tsx new file mode 100644 index 00000000000..eb895307124 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletQualitativeRange.test.tsx @@ -0,0 +1,16 @@ +import { render } from '@testing-library/react'; +import { ChartBulletQualitativeRange } from './ChartBulletQualitativeRange'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletQualitativeRange', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletQualitativeRange.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletQualitativeRange.tsx similarity index 90% rename from packages/react-charts/src/components/ChartBullet/ChartBulletQualitativeRange.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletQualitativeRange.tsx index 50a418ca43b..857e847226b 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletQualitativeRange.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletQualitativeRange.tsx @@ -1,17 +1,19 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { DataGetterPropType, DomainPropType, NumberOrCallback, PaddingProps } from 'victory-core'; import { VictoryBar } from 'victory-bar'; -import { getQualitativeRangeData } from './utils'; -import { ChartBar } from '../ChartBar'; -import { ChartContainer } from '../ChartContainer'; -import { ChartBulletStyles, ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; -import { getBulletQualitativeRangeTheme } from '../ChartUtils'; +import { getQualitativeRangeData } from './utils/chart-bullet-data'; +import { ChartBar } from '../ChartBar/ChartBar'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartBulletStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; +import { getBulletQualitativeRangeTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-bar/src/index.d.ts + * ChartBulletQualitativeRange renders a dataset as the qualitative range. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-bar/src/index.d.ts */ export interface ChartBulletQualitativeRangeProps { /** @@ -148,14 +150,6 @@ export interface ChartBulletQualitativeRangeProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -200,12 +194,11 @@ export const ChartBulletQualitativeRange: React.FunctionComponent @@ -224,7 +217,7 @@ export const ChartBulletQualitativeRange: React.FunctionComponent { if (horizontal) { @@ -245,7 +238,7 @@ export const ChartBulletQualitativeRange: React.FunctionComponent - React.cloneElement(measureComponent, { + cloneElement(measureComponent, { barWidth, data: [{ ...dataPoint }], domain, @@ -262,6 +255,7 @@ export const ChartBulletQualitativeRange: React.FunctionComponent ) : ( - {measure} + {measure} ); }; ChartBulletQualitativeRange.displayName = 'ChartBulletQualitativeRange'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/ChartBulletTitle.test.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletTitle.test.tsx new file mode 100644 index 00000000000..884f20e163c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletTitle.test.tsx @@ -0,0 +1,17 @@ +import { render } from '@testing-library/react'; +import { ChartBulletTitle } from './ChartBulletTitle'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; + +Object.values([true, false]).forEach(() => { + test('ChartBulletTitle', () => { + const { asFragment } = render(} />); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + } /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletTitle.tsx b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletTitle.tsx similarity index 84% rename from packages/react-charts/src/components/ChartBullet/ChartBulletTitle.tsx rename to packages/react-charts/src/victory/components/ChartBullet/ChartBulletTitle.tsx index cfb748b3120..aeb0635c2b7 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletTitle.tsx +++ b/packages/react-charts/src/victory/components/ChartBullet/ChartBulletTitle.tsx @@ -1,13 +1,16 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import { PaddingProps, StringOrNumberOrCallback } from 'victory-core'; -import { ChartContainer } from '../ChartContainer'; -import { ChartLabel } from '../ChartLabel'; -import { ChartLegendPosition } from '../ChartLegend'; -import { ChartBulletStyles, ChartCommonStyles, ChartThemeDefinition } from '../ChartTheme'; -import { getBulletTheme, getBulletLabelX, getBulletLabelY, getPaddingForSide } from '../ChartUtils'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartCommonStyles, ChartBulletStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getBulletLabelX, getBulletLabelY } from '../ChartUtils/chart-label'; +import { getPaddingForSide } from '../ChartUtils/chart-padding'; +import { getBulletTheme } from '../ChartUtils/chart-theme-types'; +import { getComponentTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts + * ChartBulletTitle renders the bullet chart title. */ export interface ChartBulletTitleProps { /** @@ -48,6 +51,12 @@ export interface ChartBulletTitleProps { * The legend position relation to the chart. Valid values are 'bottom', 'bottom-left', and 'right' */ legendPosition?: 'bottom' | 'bottom-left' | 'right'; + /** + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. + */ + name?: string; /** * The padding props specifies the amount of padding in number of pixels between * the edge of the chart and any rendered child components. This prop can be given @@ -94,14 +103,6 @@ export interface ChartBulletTitleProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title to render for grouped bullets */ @@ -130,18 +131,18 @@ export const ChartBulletTitle: React.FunctionComponent = ariaTitle, capHeight = 1.1, horizontal = true, - legendPosition = 'bottom' as ChartLegendPosition, + legendPosition = 'bottom', + name, padding, standalone = true, subTitle, themeColor, - themeVariant, title, titleComponent = , titlePosition, // destructure last - theme = getBulletTheme(themeColor, themeVariant), + theme = getBulletTheme(themeColor), height = horizontal ? theme.chart.height : theme.chart.width, width = horizontal ? theme.chart.width : theme.chart.height }: ChartBulletTitleProps) => { @@ -159,6 +160,7 @@ export const ChartBulletTitle: React.FunctionComponent = // Returns title const getTitle = () => { + const componentTheme = getComponentTheme(themeColor); const showBoth = title && subTitle; let labelPosition: 'bottom' | 'left' | 'top-left' = horizontal ? 'left' : 'bottom'; @@ -188,8 +190,9 @@ export const ChartBulletTitle: React.FunctionComponent = // The x and y calculations below are used to adjust the position of the title, based on padding and scale. // This ensures that when padding is adjusted, the title moves along with the chart's position. - return React.cloneElement(titleComponent, { + return cloneElement(titleComponent, { ...(showBoth && { capHeight }), + ...(name && { id: () => `${name}-${(titleComponent as any).type.displayName}` }), style: [ChartBulletStyles.label.title, ChartBulletStyles.label.subTitle], text: showBoth ? [title, subTitle] : title, textAnchor, @@ -214,7 +217,8 @@ export const ChartBulletTitle: React.FunctionComponent = dy, labelPosition }), - ...titleComponent.props + ...titleComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); }; @@ -223,7 +227,7 @@ export const ChartBulletTitle: React.FunctionComponent = {getTitle()}
    ) : ( - {getTitle()} + {getTitle()} ); }; ChartBulletTitle.displayName = 'ChartBulletTitle'; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBullet.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBullet.test.tsx.snap new file mode 100644 index 00000000000..79c255660c5 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBullet.test.tsx.snap @@ -0,0 +1,468 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletQualitativeRange 1`] = ` + +
    + + + + + + + + 0 + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartBulletQualitativeRange 2`] = ` + +
    + + + + + + + + 0 + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + Bullet chart example + + + Storage capacity + + + + + + + + 0 + + + + + + + + 100 + + + + + + + + 25 + + + + + + + + 50 + + + + + + + + 75 + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeErrorMeasure.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeErrorMeasure.test.tsx.snap new file mode 100644 index 00000000000..75180d1bb27 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeErrorMeasure.test.tsx.snap @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletComparativeErrorMeasure 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletComparativeErrorMeasure 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeMeasure.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeMeasure.test.tsx.snap new file mode 100644 index 00000000000..af43094b9b8 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeMeasure.test.tsx.snap @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletComparativeMeasure 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletComparativeMeasure 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeWarningMeasure.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeWarningMeasure.test.tsx.snap new file mode 100644 index 00000000000..9149f42388a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletComparativeWarningMeasure.test.tsx.snap @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletComparativeZeroMeasure 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletComparativeZeroMeasure 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletGroupTitle.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletGroupTitle.test.tsx.snap new file mode 100644 index 00000000000..1c8ed3fe9cd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletGroupTitle.test.tsx.snap @@ -0,0 +1,117 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletGroupTitle 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletGroupTitle 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + Text label + + + Measure details + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletPrimaryDotMeasure.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletPrimaryDotMeasure.test.tsx.snap new file mode 100644 index 00000000000..9df6374c2d3 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletPrimaryDotMeasure.test.tsx.snap @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletPrimaryDotMeasure 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletPrimaryDotMeasure 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletPrimarySegmentedMeasure.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletPrimarySegmentedMeasure.test.tsx.snap new file mode 100644 index 00000000000..c9288bc2e40 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletPrimarySegmentedMeasure.test.tsx.snap @@ -0,0 +1,140 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletPrimarySegmentedMeasure 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletPrimarySegmentedMeasure 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletQualitativeRange.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletQualitativeRange.test.tsx.snap new file mode 100644 index 00000000000..3d7835aef62 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletQualitativeRange.test.tsx.snap @@ -0,0 +1,140 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletQualitativeRange 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletQualitativeRange 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletTitle.test.tsx.snap b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletTitle.test.tsx.snap new file mode 100644 index 00000000000..0775de19682 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/__snapshots__/ChartBulletTitle.test.tsx.snap @@ -0,0 +1,109 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartBulletTitle 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartBulletTitle 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + Text label + + + Measure details + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBullet.md b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBullet.md new file mode 100644 index 00000000000..9484f65b26d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBullet.md @@ -0,0 +1,136 @@ +--- +id: Bullet chart +section: components +subsection: charts +propComponents: [ + 'ChartAxis', + 'ChartBullet', + 'ChartContainer' +] +hideDarkMode: true +--- + +import { createRef } from 'react'; +import { ChartAxis, ChartBullet, ChartContainer, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic +```ts file = "ChartBulletBasic.tsx" +``` + +### Segmented primary measure +```ts file = "ChartBulletSegmentedMeasure.tsx" + +``` + +### Responsive container with bottom aligned legend + +This demonstrates a responsive legend which wraps when items are wider than its container. + +```ts file = "ChartBulletResponsiveLegend.tsx" + +``` + +### Primary measure dot +```ts file = "ChartBulletPrimaryDot.tsx" + +``` + +### Error measure and custom axis ticks + +This is a green bullet chart with error measure and custom axis ticks with 3 legend items per row. + +```ts file = "ChartBulletErrorCustomTicks.tsx" + +``` + +### Primary measure outside range + +This is a yellow bullet chart with primary measure greater than max range. + +```ts file = "ChartBulletOutsideRange.tsx" + +``` + +### Negative primary measure + +This bullet chart with negative primary measure is for measures considered to be bad when they are low. + +```ts file = "ChartBulletNegativeMeasure.tsx" + +``` + +### Reversed with right aligned legend + +This reversed bullet chart with right aligned legend is for measures considered to be good when they are low. + +```ts file = "ChartBulletReversed.tsx" + +``` + +### Negative and positive primary measures + +This bullet chart with negative and positive primary measures has 4 legend items per row. + +```ts file = "ChartBulletNegativePositiveMeasure.tsx" + +``` + +### Vertical with segmented primary measure +```ts file = "ChartBulletVerticalSegmented.tsx" + +``` + +### Vertical primary measure outside max range +```ts file = "ChartBulletVerticalMaxRange.tsx" + +``` + +### Custom labels +```ts file = "ChartBulletCustomLabels.tsx" + +``` + +### Custom size +```ts file = "ChartBulletCustomSize.tsx" + +``` + +### Horizontal group +```ts file = "ChartBulletHorizontalGroup.tsx" + +``` + +### Vertical group +```ts file = "ChartBulletVerticalGroup.tsx" + +``` + +### Horizontal group with title +```ts file = "ChartBulletHorizontalGroupTitle.tsx" + +``` + +### Vertical group with title +```ts file = "ChartBulletVerticalGroupTitle.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBullet` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartContainer` props, see [VictoryContainer](https://formidable.com/open-source/victory/docs/victory-container) diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletBasic.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletBasic.tsx new file mode 100644 index 00000000000..9ae04a4c138 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletBasic.tsx @@ -0,0 +1,33 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y: number; +} + +export const ChartBulletBasic: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 88 }]; + const primarySegmentedMeasureData: ChartData[] = [{ name: 'Measure', y: 60 }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart1" + primarySegmentedMeasureData={primarySegmentedMeasureData} + qualitativeRangeData={qualitativeRangeData} + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletCustomLabels.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletCustomLabels.tsx new file mode 100644 index 00000000000..1d1d0209ea8 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletCustomLabels.tsx @@ -0,0 +1,52 @@ +import { ChartAxis, ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletCustomLabels: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 88 }]; + const primarySegmentedMeasureData: ChartData[] = [{ name: 'Measure', y: 60 }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + + return ( +
    + { + switch (val) { + case 0: + return 'New'; + case 25: + return 'Beginner'; + case 50: + return 'Intermediate'; + case 75: + return 'Advanced'; + case 100: + return 'Expert'; + } + }} + /> + } + comparativeWarningMeasureData={comparativeWarningMeasureData} + constrainToVisibleArea + height={150} + labels={({ datum }) => `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart12" + primarySegmentedMeasureData={primarySegmentedMeasureData} + qualitativeRangeData={qualitativeRangeData} + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletCustomSize.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletCustomSize.tsx new file mode 100644 index 00000000000..26c6497048d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletCustomSize.tsx @@ -0,0 +1,47 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletCustomSize: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [{ name: 'Measure', y: 60 }]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart13" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 50, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletErrorCustomTicks.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletErrorCustomTicks.tsx new file mode 100644 index 00000000000..9ad680132ac --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletErrorCustomTicks.tsx @@ -0,0 +1,57 @@ +import { ChartAxis, ChartBullet, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletErrorCustomTicks: React.FunctionComponent = () => { + const comparativeErrorMeasureData: ChartData[] = [{ name: 'Error', y: 120 }]; + const comparativeErrorMeasureLegendData: ChartData[] = [{ name: 'Error' }]; + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 80 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 75 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 65 }, + { name: 'Range', y: 100 }, + { name: 'Range', y: 150 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + } + comparativeErrorMeasureData={comparativeErrorMeasureData} + comparativeErrorMeasureLegendData={comparativeErrorMeasureLegendData} + comparativeWarningMeasureData={comparativeWarningMeasureData} + comparativeWarningMeasureLegendData={comparativeWarningMeasureLegendData} + constrainToVisibleArea + height={200} + labels={({ datum }) => `${datum.name}: ${datum.y}`} + legendItemsPerRow={3} + name="chart5" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 50, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + themeColor={ChartThemeColor.green} + subTitle="Measure details" + title="Text label" + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletHorizontalGroup.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletHorizontalGroup.tsx new file mode 100644 index 00000000000..0aefa3eec82 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletHorizontalGroup.tsx @@ -0,0 +1,120 @@ +import { ChartBullet, ChartContainer } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletHorizontalGroup: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 78 }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 15 }, + { name: 'Measure', y: 50 } + ]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 40 }, + { name: 'Range', y: 65 } + ]; + + return ( +
    + + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart14" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 75 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + qualitativeRangeData={qualitativeRangeData} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart15" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 300 + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart16" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 525 + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 35 }, + { name: 'Measure', y: 70 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 60 }, + { name: 'Range', y: 85 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart17" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 750 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletHorizontalGroupTitle.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletHorizontalGroupTitle.tsx new file mode 100644 index 00000000000..16f6f6aa776 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletHorizontalGroupTitle.tsx @@ -0,0 +1,122 @@ +import { ChartBullet, ChartContainer } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletHorizontalGroupTitle: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 78 }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 15 }, + { name: 'Measure', y: 50 } + ]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 40 }, + { name: 'Range', y: 65 } + ]; + + return ( +
    + + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart22" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 275 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + qualitativeRangeData={qualitativeRangeData} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart23" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 500 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart24" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 725 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 35 }, + { name: 'Measure', y: 70 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 60 }, + { name: 'Range', y: 85 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart25" + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 150, // Adjusted to accommodate labels + right: 50, + top: 950 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={600} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletNegativeMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletNegativeMeasure.tsx new file mode 100644 index 00000000000..b0c26ba3599 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletNegativeMeasure.tsx @@ -0,0 +1,49 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; + y0?: number; +} + +export const ChartBulletNegativeMeasure: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 60 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [{ name: 'Measure', y: -15 }]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 25, y0: -25 }, + { name: 'Range', y: 50 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 75 }} + minDomain={{ y: -25 }} + name="chart7" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 50, + top: 65 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletNegativePositiveMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletNegativePositiveMeasure.tsx new file mode 100644 index 00000000000..48397f2d121 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletNegativePositiveMeasure.tsx @@ -0,0 +1,60 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; + y0?: number; +} + +export const ChartBulletNegativePositiveMeasure: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 60 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: -10 }, + { name: 'Measure', y: -20 }, + { name: 'Measure', y: 10 }, + { name: 'Measure', y: 40 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [ + { name: 'Measure 1' }, + { name: 'Measure 2' }, + { name: 'Measure 3' }, + { name: 'Measure 4' } + ]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 25, y0: -25 }, + { name: 'Range', y: 50 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + legendItemsPerRow={4} + maxDomain={{ y: 75 }} + minDomain={{ y: -25 }} + name="chart9" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 50, + top: 65 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletOutsideRange.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletOutsideRange.tsx new file mode 100644 index 00000000000..577e6e16819 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletOutsideRange.tsx @@ -0,0 +1,52 @@ +import { ChartBullet, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletOutsideRange: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 80 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 75 }, + { name: 'Measure', y: 135 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 85 }, + { name: 'Range', y: 125 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + height={200} + maxDomain={{ y: 125 }} + minDomain={{ y: 50 }} + name="chart6" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 75, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + themeColor={ChartThemeColor.yellow} + subTitle="Measure details" + title="Text label" + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletPrimaryDot.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletPrimaryDot.tsx new file mode 100644 index 00000000000..ff4576d7b9d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletPrimaryDot.tsx @@ -0,0 +1,50 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletPrimaryDot: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primaryDotMeasureData: ChartData[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]; + const primaryDotMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart4" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 50, + top: 50 + }} + primaryDotMeasureData={primaryDotMeasureData} + primaryDotMeasureLegendData={primaryDotMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletResponsiveLegend.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletResponsiveLegend.tsx new file mode 100644 index 00000000000..87487601652 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletResponsiveLegend.tsx @@ -0,0 +1,87 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; + +interface ChartData { + name: string; + y?: number; +} + +export const BulletChartResponsiveLegend: React.FunctionComponent = () => { + const containerRef = React.useRef(null); + const [extraHeight, setExtraHeight] = React.useState(0); + const [width, setWidth] = React.useState(0); + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + const handleResize = (): void => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + const handleLegendAllowWrap = (newExtraHeight: number): void => { + if (newExtraHeight !== extraHeight) { + setExtraHeight(newExtraHeight); + } + }; + + const getHeight = (baseHeight: number): number => baseHeight + extraHeight; + + React.useEffect(() => { + let observer: () => void; + + if (containerRef.current) { + observer = getResizeObserver(containerRef.current, handleResize); + handleResize(); + } + return () => { + if (observer) { + observer(); + } + }; + }, []); + + const height: number = getHeight(200); + + return ( +
    + `${datum.name}: ${datum.y}`} + legendAllowWrap={handleLegendAllowWrap} + legendPosition="bottom-left" + maxDomain={{ y: 100 }} + name="chart3" + padding={{ + bottom: 50, + left: 50, + right: 50, + top: 100 // Adjusted to accommodate labels + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + titlePosition="top-left" + width={width} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletReversed.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletReversed.tsx new file mode 100644 index 00000000000..0004d2fa717 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletReversed.tsx @@ -0,0 +1,54 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletReversed: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: -88 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: -60 }, + { name: 'Measure', y: -25 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: -50 }, + { name: 'Range', y: -75 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + legendPosition="right" + legendOrientation="vertical" + maxDomain={{ y: 0 }} + minDomain={{ y: -100 }} + name="chart8" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 150, // Adjusted to accommodate legend + top: 80 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + width={700} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletSegmentedMeasure.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletSegmentedMeasure.tsx new file mode 100644 index 00000000000..d6704140bc9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletSegmentedMeasure.tsx @@ -0,0 +1,50 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletSegmentedMeasure: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart2" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 50, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + width={600} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalGroup.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalGroup.tsx new file mode 100644 index 00000000000..a7db62b3ccd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalGroup.tsx @@ -0,0 +1,124 @@ +import { ChartBullet, ChartContainer } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletVerticalGroup: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 78 }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 15 }, + { name: 'Measure', y: 50 } + ]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 40 }, + { name: 'Range', y: 65 } + ]; + + return ( +
    + + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart18" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart19" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 300, + right: 50, + top: 50 + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart20" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 550, + right: 50, + top: 50 + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 35 }, + { name: 'Measure', y: 70 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 60 }, + { name: 'Range', y: 85 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart21" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 800, + right: 50, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + qualitativeRangeData={qualitativeRangeData} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalGroupTitle.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalGroupTitle.tsx new file mode 100644 index 00000000000..a6f334c5602 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalGroupTitle.tsx @@ -0,0 +1,126 @@ +import { ChartBullet, ChartContainer } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletVerticalGroupTitle: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 78 }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 15 }, + { name: 'Measure', y: 50 } + ]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 40 }, + { name: 'Range', y: 65 } + ]; + + return ( +
    + + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart26" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 150 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={[{ name: 'Measure 1' }, { name: 'Measure 2' }]} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={[{ name: 'Range 1' }, { name: 'Range 2' }]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart27" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 300, + right: 50, + top: 150 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart28" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 550, + right: 50, + top: 150 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={[ + { name: 'Measure', y: 35 }, + { name: 'Measure', y: 70 } + ]} + qualitativeRangeData={[ + { name: 'Range', y: 60 }, + { name: 'Range', y: 85 } + ]} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart29" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 800, + right: 50, + top: 150 // Adjusted to accommodate group labels + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + qualitativeRangeData={qualitativeRangeData} + standalone={false} + subTitle="Measure details" + title="Text label" + width={500} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalMaxRange.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalMaxRange.tsx new file mode 100644 index 00000000000..b43a111e8cd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalMaxRange.tsx @@ -0,0 +1,53 @@ +import { ChartBullet, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletVerticalMaxRange: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 100 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 75 }, + { name: 'Measure', y: 135 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 85 }, + { name: 'Range', y: 125 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 125 }} + minDomain={{ y: 50 }} + name="chart11" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 400, + right: 50, + top: 50 // Adjusted to accommodate primary segmented measure tooltip + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + themeColor={ChartThemeColor.yellow} + width={500} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalSegmented.tsx b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalSegmented.tsx new file mode 100644 index 00000000000..bbb6b765508 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/examples/ChartBulletVerticalSegmented.tsx @@ -0,0 +1,51 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; + +interface ChartData { + name: string; + y?: number; +} + +export const ChartBulletVerticalSegmented: React.FunctionComponent = () => { + const comparativeWarningMeasureData: ChartData[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: ChartData[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: ChartData[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]; + const primarySegmentedMeasureLegendData: ChartData[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: ChartData[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: ChartData[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + maxDomain={{ y: 100 }} + name="chart10" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 400, + right: 50, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + width={500} + /> +
    + ); +}; diff --git a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-data.ts b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-data.ts similarity index 80% rename from packages/react-charts/src/components/ChartBullet/utils/chart-bullet-data.ts rename to packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-data.ts index ba9416b1203..509263b92b4 100644 --- a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-data.ts +++ b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-data.ts @@ -1,5 +1,5 @@ import { Data, DataGetterPropType } from 'victory-core'; -import { ChartThemeDefinition } from '../../ChartTheme'; +import { ChartThemeDefinition } from '../../ChartTheme/ChartTheme'; import { getBulletComparativeErrorMeasureTheme, getBulletComparativeMeasureTheme, @@ -8,7 +8,7 @@ import { getBulletPrimaryNegativeMeasureTheme, getBulletPrimarySegmentedMeasureTheme, getBulletQualitativeRangeTheme -} from '../../ChartUtils'; +} from '../../ChartUtils/chart-theme-types'; interface ChartBulletDataInterface { data?: any[]; @@ -16,18 +16,21 @@ interface ChartBulletDataInterface { negativeMeasureTheme?: ChartThemeDefinition; theme?: ChartThemeDefinition; themeColor?: string; - themeVariant?: string; y?: DataGetterPropType; y0?: DataGetterPropType; } +/** + * Returns comparative measure data + * + * @private Not intended as public API and subject to change + */ export const getComparativeMeasureData = ({ data, themeColor, - themeVariant, // destructure last - theme = getBulletComparativeMeasureTheme(themeColor, themeVariant), + theme = getBulletComparativeMeasureTheme(themeColor), y }: ChartBulletDataInterface) => { const datum: any[] = []; @@ -50,48 +53,58 @@ export const getComparativeMeasureData = ({ return computedData; }; +/** + * Returns comparative error measure data + * + * @private Not intended as public API and subject to change + */ export const getComparativeErrorMeasureData = ({ data, themeColor, - themeVariant, // destructure last - theme = getBulletComparativeErrorMeasureTheme(themeColor, themeVariant), + theme = getBulletComparativeErrorMeasureTheme(themeColor), y }: ChartBulletDataInterface) => getComparativeMeasureData({ data, theme, themeColor, - themeVariant, y }); +/** + * Returns comparative warning data + * + * @private Not intended as public API and subject to change + */ export const getComparativeWarningMeasureData = ({ data, themeColor, - themeVariant, // destructure last - theme = getBulletComparativeWarningMeasureTheme(themeColor, themeVariant), + theme = getBulletComparativeWarningMeasureTheme(themeColor), y }: ChartBulletDataInterface) => getComparativeMeasureData({ data, theme, themeColor, - themeVariant, y }); +/** + * Returns primary dot measure data + * + * @private Not intended as public API and subject to change + */ export const getPrimaryDotMeasureData = ({ data, invert, themeColor, - themeVariant, // destructure last - theme = getBulletPrimaryDotMeasureTheme(themeColor, themeVariant), + theme = getBulletPrimaryDotMeasureTheme(themeColor), y, y0 }: ChartBulletDataInterface) => @@ -100,20 +113,23 @@ export const getPrimaryDotMeasureData = ({ invert, theme, themeColor, - themeVariant, y, y0 }); +/** + * Returns primary segment measure data + * + * @private Not intended as public API and subject to change + */ export const getPrimarySegmentedMeasureData = ({ data, invert, themeColor, - themeVariant, // destructure last - theme = getBulletPrimarySegmentedMeasureTheme(themeColor, themeVariant), - negativeMeasureTheme = getBulletPrimaryNegativeMeasureTheme(themeColor, themeVariant), + theme = getBulletPrimarySegmentedMeasureTheme(themeColor), + negativeMeasureTheme = getBulletPrimaryNegativeMeasureTheme(themeColor), y, y0 }: ChartBulletDataInterface) => { @@ -169,14 +185,18 @@ export const getPrimarySegmentedMeasureData = ({ return [...negativeComputedData, ...positiveComputedData]; }; +/** + * Returns qualitative range data + * + * @private Not intended as public API and subject to change + */ export const getQualitativeRangeData = ({ data, invert, themeColor, - themeVariant, // destructure last - theme = getBulletQualitativeRangeTheme(themeColor, themeVariant), + theme = getBulletQualitativeRangeTheme(themeColor), y, y0 }: ChartBulletDataInterface) => { diff --git a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-domain.ts b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-domain.ts similarity index 90% rename from packages/react-charts/src/components/ChartBullet/utils/chart-bullet-domain.ts rename to packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-domain.ts index cf094f19fac..ce65712311e 100644 --- a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-domain.ts +++ b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-domain.ts @@ -1,5 +1,4 @@ -import * as React from 'react'; -import { ChartDomain, getDomains } from '../../ChartUtils'; +import { ChartDomain, getDomains } from '../../ChartUtils/chart-domain'; interface ChartBulletDomainInterface { comparativeErrorMeasureComponent?: React.ReactElement; @@ -16,7 +15,11 @@ interface ChartBulletDomainInterface { qualitativeRangeData?: any[]; } -// Returns the bullet chart's min and max domain for comparative / primary measures and qualitative range data +/** + * Returns the bullet chart's min and max domain for comparative / primary measures and qualitative range data + * + * @private Not intended as public API and subject to change + */ export const getBulletDomain = ({ comparativeErrorMeasureComponent, comparativeErrorMeasureData, diff --git a/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-size.ts b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-size.ts new file mode 100644 index 00000000000..c477d141d5e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-size.ts @@ -0,0 +1,204 @@ +import { ChartThemeDefinition } from '../../ChartTheme/ChartTheme'; +import { ChartBulletStyles } from '../../ChartTheme/ChartStyles'; +import { + getBulletComparativeErrorMeasureTheme, + getBulletComparativeMeasureTheme, + getBulletComparativeWarningMeasureTheme, + getBulletPrimaryDotMeasureTheme, + getBulletPrimarySegmentedMeasureTheme, + getBulletQualitativeRangeTheme +} from '../../ChartUtils/chart-theme-types'; + +interface ChartBulletScaleInterface { + defaultSize: number; // The default chart size from the theme + height: number; // The chart height -- not SVG height + horizontal?: boolean; // Flag indicating chart is shown horizontally + scale?: number; // The scale factor to reduce / increase the bar width + value: number; // The bar height or scatter size from the theme + width: number; // The chart width -- not SVG width +} + +/** + * Scale dimensions + * + * @private Not intended as public API and subject to change + */ +const scaleDimensions = ({ + defaultSize, + height, + horizontal = true, + scale = 1, + value, + width +}: ChartBulletScaleInterface) => { + if (horizontal && height > defaultSize) { + return value + (height - defaultSize) * scale; + } else if (horizontal) { + return value - (defaultSize - height) * scale; + } else if (width > defaultSize) { + return value + (width - defaultSize) * scale; + } + return value - (defaultSize - width) * scale; +}; + +/** + * Scale bar width per the given size properties + * + * @private Not intended as public API and subject to change + */ +const scaleBarWidth = (props: ChartBulletScaleInterface) => Math.max(scaleDimensions(props), 0); + +/** + * Scale size per the given size properties + * + * @private Not intended as public API and subject to change + */ +const scaleSize = ({ value, ...rest }: ChartBulletScaleInterface) => + Math.round( + scaleDimensions({ + scale: 1 / value, + value, + ...rest + }) + ); + +interface ChartBulletSizeInterface { + height: number; // The chart height -- not SVG height + horizontal?: boolean; // Flag indicating chart is shown horizontally + theme?: ChartThemeDefinition; + themeColor?: string; + width: number; // The chart width -- not SVG width +} + +/** + * Scale size per the given size properties + * + * @private Not intended as public API and subject to change + */ +export const getComparativeMeasureErrorWidth = ({ + height, + horizontal, + themeColor, + width, + + // destructure last + theme = getBulletComparativeErrorMeasureTheme(themeColor) +}: ChartBulletSizeInterface) => + scaleBarWidth({ + defaultSize: theme.bar.height, + height, + horizontal, + value: ChartBulletStyles.comparativeMeasureErrorWidth, + width + }); + +/** + * Returns comparative measure width + * + * @private Not intended as public API and subject to change + */ +export const getComparativeMeasureWidth = ({ + height, + horizontal, + themeColor, + width, + + // destructure last + theme = getBulletComparativeMeasureTheme(themeColor) +}: ChartBulletSizeInterface) => + scaleBarWidth({ + defaultSize: theme.bar.height, + height, + horizontal, + value: ChartBulletStyles.comparativeMeasureWidth, + width + }); + +/** + * Returns comparative measure warning width + * + * @private Not intended as public API and subject to change + */ +export const getComparativeMeasureWarningWidth = ({ + height, + horizontal, + themeColor, + width, + + // destructure last + theme = getBulletComparativeWarningMeasureTheme(themeColor) +}: ChartBulletSizeInterface) => + scaleBarWidth({ + defaultSize: theme.bar.height, + height, + horizontal, + value: ChartBulletStyles.comparativeMeasureWarningWidth, + width + }); + +/** + * Returns primary dot measure size + * + * @private Not intended as public API and subject to change + */ +export const getPrimaryDotMeasureSize = ({ + height, + horizontal, + themeColor, + width, + + // destructure last + theme = getBulletPrimaryDotMeasureTheme(themeColor) +}: ChartBulletSizeInterface) => + scaleSize({ + defaultSize: theme.group.height, + height, + horizontal, + value: ChartBulletStyles.primaryDotMeasureSize, + width + }); + +/** + * Returns primary segmented measure width + * + * @private Not intended as public API and subject to change + */ +export const getPrimarySegmentedMeasureWidth = ({ + height, + horizontal, + themeColor, + width, + + // destructure last + theme = getBulletPrimarySegmentedMeasureTheme(themeColor) +}: ChartBulletSizeInterface) => + scaleBarWidth({ + defaultSize: theme.group.height, + height, + horizontal, + scale: 0.3, + value: ChartBulletStyles.primarySegmentedMeasureWidth, + width + }); + +/** + * Returns qualitative range bar width + * + * @private Not intended as public API and subject to change + */ +export const getQualitativeRangeBarWidth = ({ + height, + horizontal, + themeColor, + width, + + // destructure last + theme = getBulletQualitativeRangeTheme(themeColor) +}: ChartBulletSizeInterface) => + scaleBarWidth({ + defaultSize: theme.group.height, + height, + horizontal, + value: ChartBulletStyles.qualitativeRangeWidth, + width + }); diff --git a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-theme.ts b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-theme.ts similarity index 81% rename from packages/react-charts/src/components/ChartBullet/utils/chart-bullet-theme.ts rename to packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-theme.ts index a44fa4b8599..7a73ae5ca0f 100644 --- a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-theme.ts +++ b/packages/react-charts/src/victory/components/ChartBullet/utils/chart-bullet-theme.ts @@ -5,8 +5,10 @@ import { getPrimarySegmentedMeasureData, getQualitativeRangeData } from './chart-bullet-data'; -import { ChartThemeDefinition } from '../../ChartTheme'; -import { getBulletTheme } from '../../ChartUtils'; +import { ChartThemeDefinition } from '../../ChartTheme/ChartTheme'; +import { getBulletTheme } from '../../ChartUtils/chart-theme-types'; +import { ChartThemeColor } from '../../ChartTheme/ChartThemeColor'; +import { SkeletonColorTheme } from '../../ChartTheme/themes/colors/skeleton-theme'; interface ChartBulletThemeInterface { comparativeErrorMeasureData?: any[]; @@ -21,9 +23,13 @@ interface ChartBulletThemeInterface { qualitativeRangeData?: any[]; qualitativeRangeLegendData?: any[]; themeColor?: string; - themeVariant?: string; } +/** + * Returns legend color scale + * + * @private Not intended as public API and subject to change + */ const getLegendColorScale = (computedData: any, legendData: any) => { const colorScale: string[] = []; legendData.forEach((data: any, index: number) => { @@ -36,6 +42,11 @@ const getLegendColorScale = (computedData: any, legendData: any) => { return colorScale; }; +/** + * Returns color scale + * + * @private Not intended as public API and subject to change + */ export const getColorScale = ({ comparativeErrorMeasureData, comparativeErrorMeasureLegendData, @@ -48,8 +59,7 @@ export const getColorScale = ({ primarySegmentedMeasureLegendData, qualitativeRangeData, qualitativeRangeLegendData, - themeColor, - themeVariant + themeColor }: ChartBulletThemeInterface): any[] => { const colorScale: any[] = []; if (primaryDotMeasureLegendData && primaryDotMeasureLegendData.length) { @@ -63,8 +73,7 @@ export const getColorScale = ({ const computedData = getPrimarySegmentedMeasureData({ data: primarySegmentedMeasureData, invert, - themeColor, - themeVariant + themeColor }); colorScale.push(...getLegendColorScale(computedData, primarySegmentedMeasureLegendData)); } @@ -72,8 +81,7 @@ export const getColorScale = ({ const computedData = getComparativeWarningMeasureData({ data: comparativeWarningMeasureData, invert, - themeColor, - themeVariant + themeColor }); colorScale.push(...getLegendColorScale(computedData, comparativeWarningMeasureLegendData)); } @@ -81,8 +89,7 @@ export const getColorScale = ({ const computedData = getComparativeErrorMeasureData({ data: comparativeErrorMeasureData, invert, - themeColor, - themeVariant + themeColor }); colorScale.push(...getLegendColorScale(computedData, comparativeErrorMeasureLegendData)); } @@ -96,7 +103,11 @@ export const getColorScale = ({ return colorScale; }; -// Get bullet chart theme with legend color scale +/** + * Returns bullet chart theme with legend color scale + * + * @private Not intended as public API and subject to change + */ export const getBulletThemeWithLegendColorScale = ({ comparativeErrorMeasureData, comparativeErrorMeasureLegendData, @@ -109,8 +120,7 @@ export const getBulletThemeWithLegendColorScale = ({ primarySegmentedMeasureLegendData, qualitativeRangeData, qualitativeRangeLegendData, - themeColor, - themeVariant + themeColor }: ChartBulletThemeInterface): ChartThemeDefinition => { const colorScale = getColorScale({ comparativeErrorMeasureData, @@ -124,11 +134,13 @@ export const getBulletThemeWithLegendColorScale = ({ primarySegmentedMeasureLegendData, qualitativeRangeData, qualitativeRangeLegendData, - themeColor, - themeVariant + themeColor }); - const theme = getBulletTheme(themeColor, themeVariant); + const theme = getBulletTheme(themeColor); theme.legend.colorScale = [...colorScale]; + if (themeColor === ChartThemeColor.skeleton) { + theme.legend.colorScale = SkeletonColorTheme.legend.colorScale; + } return theme; }; diff --git a/packages/react-charts/src/victory/components/ChartContainer/ChartContainer.test.tsx b/packages/react-charts/src/victory/components/ChartContainer/ChartContainer.test.tsx new file mode 100644 index 00000000000..ddc3ab1ad9c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartContainer/ChartContainer.test.tsx @@ -0,0 +1,27 @@ +import { render } from '@testing-library/react'; +import { ChartLegend } from '../ChartLegend/ChartLegend'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartContainer } from './ChartContainer'; + +Object.values([true, false]).forEach(() => { + test('ChartContainer', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders container via ChartLegend', () => { + const { asFragment } = render( + + } + /> + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartContainer/ChartContainer.tsx b/packages/react-charts/src/victory/components/ChartContainer/ChartContainer.tsx similarity index 87% rename from packages/react-charts/src/components/ChartContainer/ChartContainer.tsx rename to packages/react-charts/src/victory/components/ChartContainer/ChartContainer.tsx index 9cdcf239c00..59b47e53dde 100644 --- a/packages/react-charts/src/components/ChartContainer/ChartContainer.tsx +++ b/packages/react-charts/src/victory/components/ChartContainer/ChartContainer.tsx @@ -1,22 +1,23 @@ -import * as React from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { OriginType, VictoryContainer, VictoryContainerProps } from 'victory-core'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getClassName, getTheme } from '../ChartUtils'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getTheme } from '../ChartUtils/chart-theme'; +import { getClassName } from '../ChartUtils/chart-helpers'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts + * ChartContainer provides a top-level element for other Victory based components to render within. By default, + * ChartContainer renders responsive SVGs. * - * Note: VictoryContainer may support other props (e.g., children), but they're undocumented and not typed + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-core/src/victory-container/victory-container.tsx */ export interface ChartContainerProps extends VictoryContainerProps { /** * The children prop specifies the child or children that will be rendered within the container. It will be set by * whatever Victory component is rendering the container. */ - children?: React.ReactElement | React.ReactElement[]; + children?: React.ReactElement | React.ReactElement[]; /** - * The className prop specifies a className that will be applied to the outer-most div rendered by ChartContainer + * The className prop specifies a className that will be applied to the outermost div rendered by ChartContainer */ className?: string; /** @@ -29,14 +30,14 @@ export interface ChartContainerProps extends VictoryContainerProps { * * @example containerRef={(ref) => { this.chartRef = ref; }} */ - containerRef?: React.RefObject; + containerRef?: React.RefObject; /** * The desc prop specifies the description of the chart/SVG to assist with * accessibility for screen readers. The more info about the chart provided in * the description, the more usable it will be for people using screen readers. * This prop defaults to an empty string. * - * @example "Golden retreivers make up 30%, Labs make up 25%, and other dog breeds are + * @example "Golden retrievers make up 30%, Labs make up 25%, and other dog breeds are * not represented above 5% each." */ desc?: string; @@ -73,6 +74,7 @@ export interface ChartContainerProps extends VictoryContainerProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -83,7 +85,7 @@ export interface ChartContainerProps extends VictoryContainerProps { * render in the portal container. This prop defaults to Portal, and should only be overridden when changing rendered * elements from SVG to another type of element e.g., react-native-svg elements. */ - portalComponent?: React.ReactElement; + portalComponent?: React.ReactElement; /** * The portalZIndex prop determines the z-index of the div enclosing the portal component. If a portalZIndex prop is * not set, the z-index of the enclosing div will be set to 99. @@ -123,14 +125,6 @@ export interface ChartContainerProps extends VictoryContainerProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title prop specifies the title to be applied to the SVG to assist * accessibility for screen readers. The more descriptive this title is, the more @@ -150,10 +144,9 @@ export interface ChartContainerProps extends VictoryContainerProps { export const ChartContainer: React.FunctionComponent = ({ className, themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartContainerProps) => { const chartClassName = getClassName({ className }); diff --git a/packages/react-charts/src/victory/components/ChartContainer/__snapshots__/ChartContainer.test.tsx.snap b/packages/react-charts/src/victory/components/ChartContainer/__snapshots__/ChartContainer.test.tsx.snap new file mode 100644 index 00000000000..bb1f6999d9d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartContainer/__snapshots__/ChartContainer.test.tsx.snap @@ -0,0 +1,154 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartContainer 1`] = ` + +
    + +
    + +
    +
    + +`; + +exports[`ChartContainer 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders container via ChartLegend 1`] = ` + +
    + + + + + + + + Average number of pets + + + + + Cats + + + + + Dogs + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartCursorContainer/ChartCursorContainer.test.tsx b/packages/react-charts/src/victory/components/ChartCursorContainer/ChartCursorContainer.test.tsx new file mode 100644 index 00000000000..09896c2eb72 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartCursorContainer/ChartCursorContainer.test.tsx @@ -0,0 +1,36 @@ +import { render } from '@testing-library/react'; +import { ChartArea } from '../ChartArea/ChartArea'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartCursorContainer } from './ChartCursorContainer'; + +Object.values([true, false]).forEach(() => { + test('ChartVoronoiContainer', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders container via ChartGroup', () => { + const { asFragment } = render( + } height={200} width={200}> + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.tsx b/packages/react-charts/src/victory/components/ChartCursorContainer/ChartCursorContainer.tsx similarity index 80% rename from packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.tsx rename to packages/react-charts/src/victory/components/ChartCursorContainer/ChartCursorContainer.tsx index 066793f0d44..053e9ec7688 100644 --- a/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.tsx +++ b/packages/react-charts/src/victory/components/ChartCursorContainer/ChartCursorContainer.tsx @@ -1,31 +1,37 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; +import chart_global_label_Fill from '@patternfly/react-tokens/dist/esm/chart_global_label_Fill'; import hoistNonReactStatics from 'hoist-non-react-statics'; -import { CallbackArgs, CoordinatesPropType, OriginType } from 'victory-core'; +import { LineSegment, OriginType, ValueOrAccessor, VictoryLabelProps } from 'victory-core'; import { CursorCoordinatesPropType, VictoryCursorContainer, VictoryCursorContainerProps } from 'victory-cursor-container'; -import { ChartLabel } from '../ChartLabel'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getClassName, getTheme } from '../ChartUtils'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getComponentTheme, getTheme } from '../ChartUtils/chart-theme'; +import { getClassName } from '../ChartUtils/chart-helpers'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-cursor-container/src/index.d.ts + * ChartCursorContainer adds a cursor to a chart to inspect coordinates. The cursor moves with the mouse along the + * visible domain of the chart. ChartCursorContainer may be used with any Victory component that works with an x-y + * coordinate system, and should be added as the containerComponent of the top-level component. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-cursor-container/src/index.d.ts */ export interface ChartCursorContainerProps extends VictoryCursorContainerProps { /** - * he children prop specifies the child or children that will be rendered within the container. It will be set by + * The children prop specifies the child or children that will be rendered within the container. It will be set by * whatever Victory component is rendering the container. * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ - children?: React.ReactElement | React.ReactElement[]; + children?: React.ReactElement | React.ReactElement[]; /** - * The className prop specifies a className that will be applied to the outer-most div rendered by the container + * The className prop specifies a className that will be applied to the outermost div rendered by the container */ className?: string; /** @@ -52,13 +58,13 @@ export interface ChartCursorContainerProps extends VictoryCursorContainerProps { * @propType Function * example: cursorLabel={(point) => point.x} */ - cursorLabel?: (point: CoordinatesPropType, args: CallbackArgs) => any | void; + cursorLabel?: ValueOrAccessor; /** * The cursorLabelComponent prop takes a component instance which will be used to render a label for the cursor. The * new element created from the passed cursorLabelComponent will be supplied with the following props: x, y, active, * text. If cursorLabelComponent is omitted, a new ChartLabel will be created with the props described above. */ - cursorLabelComponent?: React.ReactElement; + cursorLabelComponent?: React.ReactElement; /** * The cursorLabelOffset prop determines the pixel offset of the cursor label from the cursor point. This prop should * be an Object with x and y properties, or a number to be used for both dimensions. @@ -81,7 +87,7 @@ export interface ChartCursorContainerProps extends VictoryCursorContainerProps { * the description, the more usable it will be for people using screen readers. * This prop defaults to an empty string. * - * @example "Golden retreivers make up 30%, Labs make up 25%, and other dog breeds are + * @example "Golden retrievers make up 30%, Labs make up 25%, and other dog breeds are * not represented above 5% each." */ desc?: string; @@ -131,6 +137,7 @@ export interface ChartCursorContainerProps extends VictoryCursorContainerProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -141,7 +148,7 @@ export interface ChartCursorContainerProps extends VictoryCursorContainerProps { * render in the portal container. This prop defaults to Portal, and should only be overridden when changing rendered * elements from SVG to another type of element e.g., react-native-svg elements. */ - portalComponent?: React.ReactElement; + portalComponent?: React.ReactElement; /** * The portalZIndex prop determines the z-index of the div enclosing the portal component. If a portalZIndex prop is * not set, the z-index of the enclosing div will be set to 99. @@ -183,14 +190,6 @@ export interface ChartCursorContainerProps extends VictoryCursorContainerProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the container * This value should be given as a number of pixels. If no width prop @@ -201,18 +200,28 @@ export interface ChartCursorContainerProps extends VictoryCursorContainerProps { export const ChartCursorContainer: React.FunctionComponent = ({ className, + cursorComponent = , themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), cursorLabelComponent = , // Note that Victory provides its own label component here ...rest }: ChartCursorContainerProps) => { + const componentTheme = getComponentTheme(themeColor); const chartClassName = getClassName({ className }); - const chartCursorLabelComponent = React.cloneElement(cursorLabelComponent, { + const chartCursorLabelComponent = cloneElement(cursorLabelComponent, { theme, - ...cursorLabelComponent.props + ...cursorLabelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle + }); + + // Clone so users can override cursor container props + const cursor = cloneElement(cursorComponent, { + style: { + strokeColor: chart_global_label_Fill.var + }, + ...cursorComponent.props }); // Note: theme is required by voronoiContainerMixin @@ -220,6 +229,7 @@ export const ChartCursorContainer: React.FunctionComponent +
    + +
    + +
    +
    + +`; + +exports[`ChartVoronoiContainer 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders container via ChartGroup 1`] = ` + +
    + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorFlyout.test.tsx b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorFlyout.test.tsx new file mode 100644 index 00000000000..0891b5eb8a6 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorFlyout.test.tsx @@ -0,0 +1,50 @@ +import { render } from '@testing-library/react'; +import { ChartArea } from '../ChartArea/ChartArea'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartCursorFlyout } from './ChartCursorFlyout'; +import { ChartCursorTooltip } from './ChartCursorTooltip'; +import { createContainer } from '../ChartUtils/chart-container'; + +Object.values([true, false]).forEach(() => { + test('ChartTooltip', () => { + const { asFragment } = render( + } /> + ); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('allows tooltip via container component', () => { + const CursorVoronoiContainer = createContainer('cursor', 'voronoi'); + const { asFragment } = render( + 'y: ' + point.y} + labelComponent={} />} + /> + } + height={200} + width={200} + > + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorFlyout.tsx b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorFlyout.tsx similarity index 82% rename from packages/react-charts/src/components/ChartCursorTooltip/ChartCursorFlyout.tsx rename to packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorFlyout.tsx index 1a0e58277f4..a4af55aa015 100644 --- a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorFlyout.tsx +++ b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorFlyout.tsx @@ -1,6 +1,5 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { Helpers, CommonProps, Path } from 'victory-core'; +import { cloneElement } from 'react'; +import { Helpers, OrientationTypes, Path, VictoryCommonPrimitiveProps } from 'victory-core'; import isPlainObject from 'lodash/isPlainObject'; const getVerticalPath = (props: any) => { @@ -92,10 +91,34 @@ const evaluateProps = (props: any) => { return Object.assign({}, props, { id, style }); }; -const ChartCursorFlyout = (props: any) => { - props = evaluateProps(props); +interface ChartCursorFlyoutProps extends VictoryCommonPrimitiveProps { + center?: { + x: number; + y: number; + }; + cornerRadius?: number; + datum?: object; + dx?: number; + dy?: number; + height?: number; + orientation?: OrientationTypes; + pathComponent?: React.ReactElement; + pointerLength?: number; + pointerWidth?: number; + width?: number; + x?: number; + y?: number; +} - return React.cloneElement(props.pathComponent, { +const ChartCursorFlyout = (props: ChartCursorFlyoutProps) => { + props = evaluateProps({ + pathComponent: , + role: 'presentation', + shapeRendering: 'auto', + ...props + }); + + return cloneElement(props.pathComponent, { ...props.events, style: props.style, d: getFlyoutPath(props), @@ -107,27 +130,4 @@ const ChartCursorFlyout = (props: any) => { }); }; -ChartCursorFlyout.propTypes = { - ...CommonProps.primitiveProps, - center: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }), - cornerRadius: PropTypes.number, - datum: PropTypes.object, - dx: PropTypes.number, - dy: PropTypes.number, - height: PropTypes.number, - orientation: PropTypes.oneOf(['top', 'bottom', 'left', 'right']), - pathComponent: PropTypes.element, - pointerLength: PropTypes.number, - pointerWidth: PropTypes.number, - width: PropTypes.number, - x: PropTypes.number, - y: PropTypes.number -}; - -ChartCursorFlyout.defaultProps = { - pathComponent: , - role: 'presentation', - shapeRendering: 'auto' -}; - export { ChartCursorFlyout }; diff --git a/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorTooltip.test.tsx b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorTooltip.test.tsx new file mode 100644 index 00000000000..45c1fcfe6c9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorTooltip.test.tsx @@ -0,0 +1,47 @@ +import { render } from '@testing-library/react'; +import { ChartArea } from '../ChartArea/ChartArea'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { createContainer } from '../ChartUtils/chart-container'; +import { ChartCursorTooltip } from './ChartCursorTooltip'; + +Object.values([true, false]).forEach(() => { + test('ChartCursorTooltip', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('allows tooltip via container component', () => { + const CursorVoronoiContainer = createContainer('cursor', 'voronoi'); + const { asFragment } = render( + 'y: ' + point.y} + labelComponent={} + /> + } + height={200} + width={200} + > + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.tsx b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorTooltip.tsx similarity index 92% rename from packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.tsx rename to packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorTooltip.tsx index f13cd7aa110..67a283ed8e4 100644 --- a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.tsx +++ b/packages/react-charts/src/victory/components/ChartCursorTooltip/ChartCursorTooltip.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { Helpers, @@ -9,17 +9,16 @@ import { VictoryStyleObject } from 'victory-core'; import { VictoryTooltip } from 'victory-tooltip'; -import { ChartLabel } from '../ChartLabel'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip, ChartTooltipProps } from '../ChartTooltip'; -import { getTheme, getCursorTooltipCenterOffset, getCursorTooltipPoniterOrientation } from '../ChartUtils'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip, ChartTooltipProps } from '../ChartTooltip/ChartTooltip'; +import { getCursorTooltipCenterOffset, getCursorTooltipPoniterOrientation } from '../ChartUtils/chart-tooltip'; +import { getTheme } from '../ChartUtils/chart-theme'; import { ChartCursorFlyout } from './ChartCursorFlyout'; /** * This tooltip has default values intended for use with a cursor container. * - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-tooltip/src/index.d.ts + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-tooltip/src/index.d.ts */ export interface ChartCursorTooltipProps extends ChartTooltipProps { /** @@ -33,7 +32,7 @@ export interface ChartCursorTooltipProps extends ChartTooltipProps { /** * The angle prop specifies the angle to rotate the tooltip around its origin point. */ - angle?: string | number; + angle?: number; /** * The center prop determines the position of the center of the tooltip flyout. This prop should be given as an object * that describes the desired x and y svg coordinates of the center of the tooltip. This prop is useful for @@ -144,6 +143,7 @@ export interface ChartCursorTooltipProps extends ChartTooltipProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ height?: number; @@ -226,7 +226,7 @@ export interface ChartCursorTooltipProps extends ChartTooltipProps { * * @propType number | string | Function | string[] | number[] */ - text?: StringOrNumberOrCallback | string[] | number[]; + text?: string[] | StringOrNumberOrCallback; /** * The theme prop specifies a theme to use for determining styles and layout properties for a component. Any styles or * props defined in theme may be overwritten by props specified on the component instance. @@ -242,14 +242,6 @@ export interface ChartCursorTooltipProps extends ChartTooltipProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * This prop refers to the width of the svg that ChartCursorTooltip is rendered within. This prop is passed from * parents of ChartCursorTooltip, and should not be set manually. In versions before ^33.0.0 this prop referred to the @@ -257,6 +249,7 @@ export interface ChartCursorTooltipProps extends ChartTooltipProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ width?: number; @@ -273,15 +266,13 @@ export interface ChartCursorTooltipProps extends ChartTooltipProps { export const ChartCursorTooltip: React.FunctionComponent = ({ constrainToVisibleArea = true, flyoutComponent = , - labelComponent = , labelTextAnchor = 'start', showPointer = true, style, themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), centerOffset = getCursorTooltipCenterOffset({ offsetCursorDimensionX: true, theme }), pointerOrientation = getCursorTooltipPoniterOrientation({ horizontal: true, theme }), pointerLength = showPointer && theme && theme.tooltip ? theme.tooltip.pointerLength : 0, @@ -296,11 +287,11 @@ export const ChartCursorTooltip: React.FunctionComponent { - let _pointerLength = Helpers.evaluateProp(pointerLength); + let _pointerLength = Helpers.evaluateProp(pointerLength, undefined); if (showPointer && _pointerLength === 0) { - _pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength) : 10; + _pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength, undefined) : 10; } - return React.cloneElement(flyoutComponent, { + return cloneElement(flyoutComponent, { pointerLength: _pointerLength, pointerWidth, ...flyoutComponent.props @@ -312,7 +303,6 @@ export const ChartCursorTooltip: React.FunctionComponent`; + +exports[`ChartTooltip 2`] = ``; + +exports[`allows tooltip via container component 1`] = ` + +
    + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartCursorTooltip/__snapshots__/ChartCursorTooltip.test.tsx.snap b/packages/react-charts/src/victory/components/ChartCursorTooltip/__snapshots__/ChartCursorTooltip.test.tsx.snap new file mode 100644 index 00000000000..1440f81d9dd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartCursorTooltip/__snapshots__/ChartCursorTooltip.test.tsx.snap @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartCursorTooltip 1`] = ``; + +exports[`ChartCursorTooltip 2`] = ``; + +exports[`allows tooltip via container component 1`] = ` + +
    + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartDonut/ChartDonut.test.tsx b/packages/react-charts/src/victory/components/ChartDonut/ChartDonut.test.tsx new file mode 100644 index 00000000000..7b917f77cdc --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/ChartDonut.test.tsx @@ -0,0 +1,24 @@ +import { render } from '@testing-library/react'; +import { ChartDonut } from './ChartDonut'; + +Object.values([true, false]).forEach(() => { + test('ChartDonut', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartDonut/ChartDonut.tsx b/packages/react-charts/src/victory/components/ChartDonut/ChartDonut.tsx similarity index 84% rename from packages/react-charts/src/components/ChartDonut/ChartDonut.tsx rename to packages/react-charts/src/victory/components/ChartDonut/ChartDonut.tsx index 74c3213547a..8a24a7cb11d 100644 --- a/packages/react-charts/src/components/ChartDonut/ChartDonut.tsx +++ b/packages/react-charts/src/victory/components/ChartDonut/ChartDonut.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -17,12 +17,16 @@ import { VictoryStyleInterface } from 'victory-core'; import { SliceProps, VictoryPie, VictorySliceLabelPositionType } from 'victory-pie'; -import { getDonutTheme } from '../ChartUtils/chart-theme'; -import { ChartContainer } from '../ChartContainer'; -import { ChartLabel } from '../ChartLabel'; -import { ChartPie, ChartPieLegendPosition, ChartPieProps } from '../ChartPie'; -import { ChartCommonStyles, ChartDonutStyles, ChartThemeDefinition } from '../ChartTheme'; -import { getPieLabelX, getPieLabelY, getPaddingForSide } from '../ChartUtils'; +import { getDonutTheme } from '../ChartUtils/chart-theme-types'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartPie, ChartPieProps } from '../ChartPie/ChartPie'; +import { ChartDonutStyles } from '../ChartTheme/ChartStyles'; +import { ChartCommonStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getPaddingForSide } from '../ChartUtils/chart-padding'; +import { getPieLabelX, getPieLabelY } from '../ChartUtils/chart-label'; +import { getComponentTheme } from '../ChartUtils/chart-theme'; interface ChartDonutSubTitleInterface { dy?: number; @@ -35,26 +39,10 @@ interface ChartDonutTitleInterface { titles?: string | string[]; } -export enum ChartDonutLabelPosition { - centroid = 'centroid', - endAngle = 'endAngle', - startAngle = 'startAngle' -} - -export enum ChartDonutSortOrder { - ascending = 'ascending', - descending = 'descending' -} - -export enum ChartDonutSubTitlePosition { - bottom = 'bottom', - center = 'center', - right = 'right' -} - /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-pie/src/index.d.ts + * ChartDonut renders a dataset as a donut chart. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-pie/src/index.d.ts */ export interface ChartDonutProps extends ChartPieProps { /** @@ -184,7 +172,7 @@ export interface ChartDonutProps extends ChartPieProps { * events. The eventKey may optionally be used to select a single element by index rather than * an entire set. The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -232,6 +220,19 @@ export interface ChartDonutProps extends ChartPieProps { * to a tag on web, and a react-native-svg tag on mobile */ groupComponent?: React.ReactElement; + /** + * The hasPatterns prop is an optional prop that indicates whether a pattern is shown for a chart. + * SVG patterns are dynamically generated (unique to each chart) in order to apply colors from the selected + * color theme or custom color scale. Those generated patterns are applied in a specific order (via a URL), similar + * to the color theme ordering defined by PatternFly. If the multi-color theme was in use; for example, colorized + * patterns would be displayed in that same order. Create custom patterns via the patternScale prop. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example hasPatterns={ true } + * @example hasPatterns={[ true, true, false ]} + */ + hasPatterns?: boolean | boolean[]; /** * Specifies the height the svg viewBox of the chart container. This value should be given as a * number of pixels. @@ -293,12 +294,20 @@ export interface ChartDonutProps extends ChartPieProps { */ labels?: string[] | number[] | ((data: any) => string | number | null); /** - * Allows legend items to wrap. A value of true allows the legend to wrap onto the next line - * if its container is not wide enough. + * Allows legend items to wrap onto the next line if the chart is not wide enough. + * + * Note that the chart's SVG height and width are 100% by default, so it can be responsive itself. However, if you + * define the height and width of the chart's parent container, you must accommodate for extra legend height due to + * legend items wrapping onto the next line. When the height of the chart's parent container is too small, some legend + * items may not be visible. + * + * Alternatively, a callback function may be provided, which will be called after the legend's itemsPerRow property + * has been calculated. The value provided can be used to increase the chart's parent container height as legend + * items wrap onto the next line. If no adjustment is necessary, the value will be zero. * * Note: This is overridden by the legendItemsPerRow property */ - legendAllowWrap?: boolean; + legendAllowWrap?: boolean | ((extraHeight: number) => void); /** * The legend component to render with chart. * @@ -338,7 +347,13 @@ export interface ChartDonutProps extends ChartPieProps { */ legendPosition?: 'bottom' | 'right'; /** - * The name prop is used to reference a component instance when defining shared events. + * Text direction of the legend labels. + */ + legendDirection?: 'ltr' | 'rtl'; + /** + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. */ name?: string; /** @@ -356,6 +371,16 @@ export interface ChartDonutProps extends ChartPieProps { * @propType number | Function */ padAngle?: NumberOrCallback; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; /** * The padding props specifies the amount of padding in number of pixels between * the edge of the chart and any rendered child components. This prop can be given @@ -377,6 +402,7 @@ export interface ChartDonutProps extends ChartPieProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -456,14 +482,6 @@ export interface ChartDonutProps extends ChartPieProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title for the donut chart */ @@ -559,8 +577,9 @@ export const ChartDonut: React.FunctionComponent = ({ capHeight = 1.1, containerComponent = , innerRadius, - legendAllowWrap, - legendPosition = ChartCommonStyles.legend.position as ChartPieLegendPosition, + legendPosition = ChartCommonStyles.legend.position, + legendDirection = 'ltr', + name, padAngle, padding, radius, @@ -569,16 +588,17 @@ export const ChartDonut: React.FunctionComponent = ({ subTitleComponent, subTitlePosition = ChartDonutStyles.label.subTitlePosition, themeColor, - themeVariant, title, titleComponent = , // destructure last - theme = getDonutTheme(themeColor, themeVariant), + theme = getDonutTheme(themeColor), height = theme.pie.height, width = theme.pie.width, ...rest }: ChartDonutProps) => { + const componentTheme = getComponentTheme(themeColor); + const defaultPadding = { bottom: getPaddingForSide('bottom', padding, theme.pie.padding), left: getPaddingForSide('left', padding, theme.pie.padding), @@ -586,14 +606,14 @@ export const ChartDonut: React.FunctionComponent = ({ top: getPaddingForSide('top', padding, theme.pie.padding) }; const chartRadius = radius - ? radius + ? Helpers.evaluateProp(radius, undefined) : Helpers.getRadius({ height, width, padding: defaultPadding }); - const chartInnerRadius = innerRadius ? innerRadius : chartRadius - 9; // Todo: Add pf-core variable - const centerSubTitle = subTitle && subTitlePosition === ChartDonutSubTitlePosition.center; + const chartInnerRadius = innerRadius ? Helpers.evaluateProp(innerRadius, undefined) : chartRadius - 9; // Todo: Add pf-core variable + const centerSubTitle = subTitle && subTitlePosition === 'center'; // Returns title and subtitle const getAllTitles = () => { @@ -604,10 +624,10 @@ export const ChartDonut: React.FunctionComponent = ({ }); } return ( - + {getTitle({ titles: title, dy: centerSubTitle ? -8 : 0 })} {getSubTitle({ textComponent: subTitleComponent, dy: centerSubTitle ? 15 : 0 })} - + ); }; @@ -621,7 +641,8 @@ export const ChartDonut: React.FunctionComponent = ({ } const subTitleProps = textComponent.props ? textComponent.props : {}; - return React.cloneElement(textComponent, { + return cloneElement(textComponent, { + ...(name && { id: `${name}-${(textComponent as any).type.displayName}-subTitle` }), key: 'pf-chart-donut-subtitle', style: ChartDonutStyles.label.subTitle, text: subTitle, @@ -641,7 +662,8 @@ export const ChartDonut: React.FunctionComponent = ({ padding: defaultPadding, width }), - ...subTitleProps + ...subTitleProps, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); }; @@ -652,8 +674,9 @@ export const ChartDonut: React.FunctionComponent = ({ } const titleProps = titleComponent ? titleComponent.props : {}; - return React.cloneElement(titleComponent, { + return cloneElement(titleComponent, { ...(Array.isArray(titles) && { capHeight }), // Use capHeight with multiple labels + ...(name && { id: `${name}-${(titleComponent as any).type.displayName}-title` }), key: 'pf-chart-donut-title', style: styles, text: titles, @@ -673,7 +696,8 @@ export const ChartDonut: React.FunctionComponent = ({ padding: defaultPadding, width }), - ...titleProps + ...titleProps, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); }; @@ -683,20 +707,22 @@ export const ChartDonut: React.FunctionComponent = ({ height={height} innerRadius={chartInnerRadius > 0 ? chartInnerRadius : 0} key="pf-chart-donut-pie" - legendAllowWrap={legendAllowWrap} legendPosition={legendPosition} + legendDirection={legendDirection} + name={name} padAngle={padAngle !== undefined ? padAngle : getPadAngle} padding={padding} radius={chartRadius > 0 ? chartRadius : 0} standalone={false} theme={theme} + themeColor={themeColor} width={width} {...rest} /> ); // Clone so users can override container props - const container = React.cloneElement( + const container = cloneElement( containerComponent, { desc: ariaDesc, @@ -710,12 +736,12 @@ export const ChartDonut: React.FunctionComponent = ({ ); return standalone ? ( - {container} + {container} ) : ( - + {chart} {getAllTitles()} - + ); }; ChartDonut.displayName = 'ChartDonut'; diff --git a/packages/react-charts/src/victory/components/ChartDonut/__snapshots__/ChartDonut.test.tsx.snap b/packages/react-charts/src/victory/components/ChartDonut/__snapshots__/ChartDonut.test.tsx.snap new file mode 100644 index 00000000000..43d101b3f69 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/__snapshots__/ChartDonut.test.tsx.snap @@ -0,0 +1,182 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartDonut 1`] = ` + +
    + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartDonut 2`] = ` + +
    + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonut.md b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonut.md new file mode 100644 index 00000000000..93d9d732e36 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonut.md @@ -0,0 +1,69 @@ +--- +id: Donut chart +section: components +subsection: charts +propComponents: [ + 'ChartDonut' +] +hideDarkMode: true +--- + +import { ChartDonut, ChartThemeColor } from '@patternfly/react-charts/victory'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic +```ts file = "ChartDonutBasic.tsx" + +``` + +### Right aligned legend +```ts file = "ChartDonutRightAlignedLegend.tsx" + +``` + +### Multi-color (ordered) with right aligned legend +```ts file = "ChartDonutMultiColor.tsx" + +``` + +### Bottom aligned legend +```ts file = "ChartDonutBottomAlignedLegend.tsx" + +``` + +### Small +```ts file = "ChartDonutSmall.tsx" + +``` + +### Small with right aligned legend +```ts file = "ChartDonutSmallRightLegend.tsx" + +``` + +### Small with bottom aligned subtitle +```ts file = "ChartDonutSmallBottomSubtitle.tsx" + +``` + +### Small with right aligned subtitle +```ts file = "ChartDonutSmallRightSubtitle.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `ChartDonut` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutBasic.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutBasic.tsx new file mode 100644 index 00000000000..c0370f8a259 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutBasic.tsx @@ -0,0 +1,29 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x: string; + y: number; +} + +export const ChartDonutBasic: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + name="chart1" + subTitle="Pets" + title="100" + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutBottomAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutBottomAlignedLegend.tsx new file mode 100644 index 00000000000..33f5581d8ff --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutBottomAlignedLegend.tsx @@ -0,0 +1,43 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartDonutBottomAlignedLegend: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendPosition="bottom" + legendWidth={225} + name="chart4" + padding={{ + bottom: 65, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + subTitle="Pets" + title="100" + width={300} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutMultiColor.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutMultiColor.tsx new file mode 100644 index 00000000000..ef32201a641 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutMultiColor.tsx @@ -0,0 +1,42 @@ +import { ChartDonut, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartDonutMultiColor: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart3" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + title="100" + themeColor={ChartThemeColor.multiOrdered} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutRightAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutRightAlignedLegend.tsx new file mode 100644 index 00000000000..b1419a9d25b --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutRightAlignedLegend.tsx @@ -0,0 +1,41 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartDonutRightAlignedLegend: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart2" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + title="100" + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmall.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmall.tsx new file mode 100644 index 00000000000..e238a12be99 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmall.tsx @@ -0,0 +1,31 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x: string; + y: number; +} + +export const ChartDonutSmall: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + name="chart5" + subTitle="Pets" + title="100" + width={150} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallBottomSubtitle.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallBottomSubtitle.tsx new file mode 100644 index 00000000000..8233d9a10cd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallBottomSubtitle.tsx @@ -0,0 +1,43 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartDonutSmallBottomSubtitle: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart7" + padding={{ + bottom: 25, // Adjusted to accommodate subTitle + left: 20, + right: 145, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + subTitlePosition="bottom" + title="100" + width={275} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallRightLegend.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallRightLegend.tsx new file mode 100644 index 00000000000..b768192bb4a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallRightLegend.tsx @@ -0,0 +1,42 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartDonutSmallRightLegend: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart6" + padding={{ + bottom: 20, + left: 20, + right: 145, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + title="100" + width={275} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallRightSubtitle.tsx b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallRightSubtitle.tsx new file mode 100644 index 00000000000..6d52feedf1f --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonut/examples/ChartDonutSmallRightSubtitle.tsx @@ -0,0 +1,42 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartDonutSmallRightSubtitle: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendPosition="bottom" + name="chart8" + padding={{ + bottom: 70, // Adjusted to accommodate legend + left: 20, + right: 50, // Adjusted to accommodate subTitle + top: 20 + }} + subTitle="Pets" + subTitlePosition="right" + title="100" + width={300} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutThreshold.test.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutThreshold.test.tsx new file mode 100644 index 00000000000..44642d5fd7f --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutThreshold.test.tsx @@ -0,0 +1,24 @@ +import { render } from '@testing-library/react'; +import { ChartDonutThreshold } from './ChartDonutThreshold'; + +Object.values([true, false]).forEach(() => { + test('ChartDonutThreshold', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutThreshold.tsx similarity index 84% rename from packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.tsx rename to packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutThreshold.tsx index f7b8988b68a..87be22d4bb6 100644 --- a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.tsx +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutThreshold.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { Children, cloneElement, Fragment, isValidElement } from 'react'; import { AnimatePropTypeInterface, CategoryPropType, @@ -18,42 +18,17 @@ import { } from 'victory-core'; import { SliceProps, VictoryPie } from 'victory-pie'; import hoistNonReactStatics from 'hoist-non-react-statics'; -import { ChartContainer } from '../ChartContainer'; -import { ChartDonut, ChartDonutProps } from '../ChartDonut'; -import { ChartDonutStyles, ChartThemeDefinition } from '../ChartTheme'; -import { getDonutThresholdDynamicTheme, getDonutThresholdStaticTheme, getPaddingForSide } from '../ChartUtils'; - -export enum ChartDonutThresholdDonutOrientation { - left = 'left', - right = 'right', - top = 'top' -} - -export enum ChartDonutThresholdLabelOrientation { - horizontal = 'horizontal', - vertical = 'vertical' -} - -export enum ChartDonutThresholdLabelPosition { - centroid = 'centroid', - endAngle = 'endAngle', - startAngle = 'startAngle' -} - -export enum ChartDonutThresholdSortOrder { - ascending = 'ascending', - descending = 'descending' -} - -export enum ChartDonutThresholdSubTitlePosition { - bottom = 'bottom', - center = 'center', - right = 'right' -} +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartDonut, ChartDonutProps } from '../ChartDonut/ChartDonut'; +import { ChartDonutStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getPaddingForSide } from '../ChartUtils/chart-padding'; +import { getDonutThresholdDynamicTheme, getDonutThresholdStaticTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-pie/src/index.d.ts + * ChartDonutThreshold renders a dataset as a donut threshold chart. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-pie/src/index.d.ts */ export interface ChartDonutThresholdProps extends ChartDonutProps { /** @@ -101,6 +76,7 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ children?: React.ReactElement; @@ -171,7 +147,7 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { * * Note: Overridden by containerComponent * - * @example "Golden retreivers make up 30%, Labs make up 25%, and other dog breeds are + * @example "Golden retrievers make up 30%, Labs make up 25%, and other dog breeds are * not represented above 5% each." */ desc?: string; @@ -194,7 +170,7 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { * events. The eventKey may optionally be used to select a single element by index rather than * an entire set. The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -242,6 +218,19 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { * to a tag on web, and a react-native-svg tag on mobile */ groupComponent?: React.ReactElement; + /** + * The hasPatterns prop is an optional prop that indicates whether a pattern is shown for a chart. + * SVG patterns are dynamically generated (unique to each chart) in order to apply colors from the selected + * color theme or custom color scale. Those generated patterns are applied in a specific order (via a URL), similar + * to the color theme ordering defined by PatternFly. If the multi-color theme was in use; for example, colorized + * patterns would be displayed in that same order. Create custom patterns via the patternScale prop. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example hasPatterns={ true } + * @example hasPatterns={[ true, true, false ]} + */ + hasPatterns?: boolean | boolean[]; /** * Specifies the height the svg viewBox of the chart container. This value should be given as a number of pixels. * @@ -280,7 +269,9 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { */ labels?: string[] | number[] | ((data: any) => string | number | null); /** - * The name prop is used to reference a component instance when defining shared events. + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. */ name?: string; /** @@ -307,6 +298,16 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { * @propType number | { top: number, bottom: number, left: number, right: number } */ padding?: PaddingProps; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; /** * Specifies the radius of the chart. If this property is not provided it is computed * from width, height, and padding props @@ -319,13 +320,10 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; - /** - * This will show the static, unused portion of the donut chart - */ - showStatic?: boolean; /** * Use the sortKey prop to indicate how data should be sorted. This prop * is given directly to the lodash sortBy function to be executed on the @@ -384,16 +382,11 @@ export interface ChartDonutThresholdProps extends ChartDonutProps { * Note: Not compatible with theme prop * * @example themeColor={ChartThemeColor.blue} - */ - themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop * - * @example themeVariant={ChartThemeVariant.light} + * @private Not intended as public API and subject to change + * @hide */ - themeVariant?: string; + themeColor?: string; /** * The title for the donut chart */ @@ -440,22 +433,24 @@ export const ChartDonutThreshold: React.FunctionComponent, data = [], + hasPatterns, invert = false, labels = [], // Don't show any tooltip labels by default, let consumer override if needed + name, padding, radius, standalone = true, - subTitlePosition = ChartDonutStyles.label.subTitlePosition as ChartDonutThresholdSubTitlePosition, + subTitlePosition = ChartDonutStyles.label.subTitlePosition, themeColor, - themeVariant, x, y, // destructure last - theme = getDonutThresholdStaticTheme(themeColor, themeVariant, invert), + theme = getDonutThresholdStaticTheme(themeColor, invert), height = theme.pie.height, width = theme.pie.width, ...rest @@ -467,7 +462,7 @@ export const ChartDonutThreshold: React.FunctionComponent - React.Children.toArray(children).map((child, index) => { - if (React.isValidElement(child)) { - const { data: childData, ...childProps } = child.props; + Children.toArray(children).map((child, index) => { + if (isValidElement(child)) { + const { data: childData, ...childProps } = child.props as any; const datum = Data.formatData([childData], childProps, ['x', 'y']); // Format child data independently of this component's props - const dynamicTheme = - childProps.theme || - getDonutThresholdDynamicTheme(childProps.themeColor || themeColor, childProps.themeVariant || themeVariant); - - return React.cloneElement(child, { + const dynamicTheme = childProps.theme || getDonutThresholdDynamicTheme(childProps.themeColor || themeColor); + return cloneElement(child, { + ...(hasPatterns && { hasPatterns: true }), // Enable ChartDonutUtilization patterns constrainToVisibleArea, data: childData, endAngle: 360 * (datum[0]._y ? datum[0]._y / 100 : 0), height, + ...(name && + typeof (child as any).name !== undefined && { + name: `${name}-${(child as any).type.displayName}-${index}` + }), invert, + isStatic: false, key: `pf-chart-donut-threshold-child-${index}`, padding: defaultPadding, + patternUnshiftIndex: computedData.length, radius: chartRadius - 14, // Donut utilization radius is threshold radius minus 14px spacing - showStatic: false, standalone: false, subTitlePosition: childProps.subTitlePosition || subTitlePosition, theme: dynamicTheme, + themeColor, width, ...childProps }); @@ -536,21 +536,25 @@ export const ChartDonutThreshold: React.FunctionComponent ); // Clone so users can override container props - const container = React.cloneElement( + const container = cloneElement( containerComponent, { desc: ariaDesc, @@ -564,12 +568,12 @@ export const ChartDonutThreshold: React.FunctionComponent{container} + {container} ) : ( - + {chart} {renderChildren()} - + ); }; ChartDonutThreshold.displayName = 'ChartDonutThreshold'; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutUtilization.test.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutUtilization.test.tsx new file mode 100644 index 00000000000..5cb9efefbfe --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutUtilization.test.tsx @@ -0,0 +1,14 @@ +import { render } from '@testing-library/react'; +import { ChartDonutUtilization } from './ChartDonutUtilization'; + +Object.values([true, false]).forEach(() => { + test('ChartDonutUtilization', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutUtilization.tsx similarity index 85% rename from packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.tsx rename to packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutUtilization.tsx index 0c7abca25c0..64f7c39c535 100644 --- a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.tsx +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/ChartDonutUtilization.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import orderBy from 'lodash/orderBy'; import { @@ -18,41 +18,16 @@ import { VictoryStyleInterface } from 'victory-core'; import { SliceProps, VictoryPie, VictorySliceLabelPositionType } from 'victory-pie'; -import { ChartContainer } from '../ChartContainer'; -import { ChartDonut, ChartDonutProps } from '../ChartDonut'; -import { ChartCommonStyles, ChartThemeDefinition, ChartDonutUtilizationStyles } from '../ChartTheme'; -import { getDonutUtilizationTheme } from '../ChartUtils'; - -export enum ChartDonutUtilizationLabelPosition { - centroid = 'centroid', - endAngle = 'endAngle', - startAngle = 'startAngle' -} - -export enum ChartDonutUtilizationLegendOrientation { - horizontal = 'horizontal', - vertical = 'vertical' -} - -export enum ChartDonutUtilizationLegendPosition { - bottom = 'bottom', - right = 'right' -} - -export enum ChartDonutUtilizationSortOrder { - ascending = 'ascending', - descending = 'descending' -} - -export enum ChartDonutUtilizationSubTitlePosition { - bottom = 'bottom', - center = 'center', - right = 'right' -} +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartDonut, ChartDonutProps } from '../ChartDonut/ChartDonut'; +import { ChartCommonStyles, ChartDonutUtilizationStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getDonutUtilizationTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-pie/src/index.d.ts + * ChartDonutUtilization renders a dataset as a donut utilization chart. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-pie/src/index.d.ts */ export interface ChartDonutUtilizationProps extends ChartDonutProps { /** @@ -171,7 +146,7 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { * * Note: Overridden by containerComponent * - * @example "Golden retreivers make up 30%, Labs make up 25%, and other dog breeds are + * @example "Golden retrievers make up 30%, Labs make up 25%, and other dog breeds are * not represented above 5% each." */ desc?: string; @@ -194,7 +169,7 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { * events. The eventKey may optionally be used to select a single element by index rather than * an entire set. The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -243,6 +218,19 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { * to a tag on web, and a react-native-svg tag on mobile */ groupComponent?: React.ReactElement; + /** + * The hasPatterns prop is an optional prop that indicates whether a pattern is shown for a chart. + * SVG patterns are dynamically generated (unique to each chart) in order to apply colors from the selected + * color theme or custom color scale. Those generated patterns are applied in a specific order (via a URL), similar + * to the color theme ordering defined by PatternFly. If the multi-color theme was in use; for example, colorized + * patterns would be displayed in that same order. Create custom patterns via the patternScale prop. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example hasPatterns={ true } + * @example hasPatterns={[ true, true, false ]} + */ + hasPatterns?: boolean | boolean[]; /** * Specifies the height the svg viewBox of the chart container. This value should be given as a * number of pixels. @@ -268,12 +256,29 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { */ invert?: boolean; /** - * Allows legend items to wrap. A value of true allows the legend to wrap onto the next line - * if its container is not wide enough. + * This will show the static, unused portion of the donut utilization chart. + * + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + isStatic?: boolean; + /** + * Allows legend items to wrap onto the next line if the chart is not wide enough. + * + * Note that the chart's SVG height and width are 100% by default, so it can be responsive itself. However, if you + * define the height and width of the chart's parent container, you must accommodate for extra legend height due to + * legend items wrapping onto the next line. When the height of the chart's parent container is too small, some legend + * items may not be visible. + * + * Alternatively, a callback function may be provided, which will be called after the legend's itemsPerRow property + * has been calculated. The value provided can be used to increase the chart's parent container height as legend + * items wrap onto the next line. If no adjustment is necessary, the value will be zero. * * Note: This is overridden by the legendItemsPerRow property */ - legendAllowWrap?: boolean; + legendAllowWrap?: boolean | ((extraHeight: number) => void); /** * The labelComponent prop takes in an entire label component which will be used * to create a label for the area. The new element created from the passed labelComponent @@ -332,6 +337,10 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { * cases, the legend may not be visible until enough padding is applied. */ legendPosition?: 'bottom' | 'right'; + /** + * Text direction of the legend labels. + */ + legendDirection?: 'ltr' | 'rtl'; /** * The labelRadius prop defines the radius of the arc that will be used for positioning each slice label. * If this prop is not set, the label radius will default to the radius of the pie + label padding. @@ -350,7 +359,9 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { */ labels?: string[] | number[] | ((data: any) => string | number | null); /** - * The name prop is used to reference a component instance when defining shared events. + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. */ name?: string; /** @@ -378,28 +389,40 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { */ padding?: PaddingProps; /** - * Specifies the radius of the chart. If this property is not provided it is computed - * from width, height, and padding props + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. * - * @propType number | Function + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} */ - radius?: NumberOrCallback; + patternScale?: string[]; /** - * The sharedEvents prop is used internally to coordinate events between components. + * Moves the given pattern index to top of scale, used to sync patterns with ChartDonutThreshold * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ - sharedEvents?: { events: any[]; getEventState: Function }; + patternUnshiftIndex?: number; /** - * This will show the static, unused portion of the donut chart. + * Specifies the radius of the chart. If this property is not provided it is computed + * from width, height, and padding props + * + * @propType number | Function + */ + radius?: NumberOrCallback; + /** + * The sharedEvents prop is used internally to coordinate events between components. * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ - showStatic?: boolean; + sharedEvents?: { events: any[]; getEventState: Function }; /** * Use the sortKey prop to indicate how data should be sorted. This prop * is given directly to the lodash sortBy function to be executed on the @@ -476,14 +499,6 @@ export interface ChartDonutUtilizationProps extends ChartDonutProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title for the donut chart label */ @@ -572,21 +587,22 @@ export const ChartDonutUtilization: React.FunctionComponent, data, invert = false, - legendPosition = ChartCommonStyles.legend.position as ChartDonutUtilizationLegendPosition, + isStatic = true, + legendPosition = ChartCommonStyles.legend.position, + legendDirection = 'ltr', padding, - showStatic = true, standalone = true, themeColor, - themeVariant, thresholds, x, y, // destructure last - theme = getDonutUtilizationTheme(themeColor, themeVariant), + theme = getDonutUtilizationTheme(themeColor), height = theme.pie.height, width = theme.pie.width, ...rest @@ -595,7 +611,7 @@ export const ChartDonutUtilization: React.FunctionComponent { const datum = getData(); const computedData: [{ x?: any; y: any }] = [{ x: datum[0]._x, y: datum[0]._y || 0 }]; - if (showStatic) { + if (isStatic) { computedData.push({ y: datum[0]._x ? Math.abs(100 - datum[0]._y) : 100 }); } return computedData; @@ -628,9 +644,8 @@ export const ChartDonutUtilization: React.FunctionComponent { const newTheme = { ...theme }; - - if (data) { - const datum = getData(); + const datum = getData(); + if (datum) { const donutThresholds = getDonutThresholds(); const mergeThemeProps = (i: number) => { // Merge just the first color of dynamic (blue, green, etc.) with static (gray) for expected colorScale @@ -664,20 +679,23 @@ export const ChartDonutUtilization: React.FunctionComponent ); // Clone so users can override container props - const container = React.cloneElement( + const container = cloneElement( containerComponent, { desc: ariaDesc, @@ -690,7 +708,7 @@ export const ChartDonutUtilization: React.FunctionComponent{container} : {chart}; + return standalone ? {container} : {chart}; }; ChartDonutUtilization.displayName = 'ChartDonutUtilization'; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/__snapshots__/ChartDonutThreshold.test.tsx.snap b/packages/react-charts/src/victory/components/ChartDonutUtilization/__snapshots__/ChartDonutThreshold.test.tsx.snap new file mode 100644 index 00000000000..ed2911f81a7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/__snapshots__/ChartDonutThreshold.test.tsx.snap @@ -0,0 +1,133 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartDonutThreshold 1`] = ` + +
    + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartDonutThreshold 2`] = ` + +
    + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/__snapshots__/ChartDonutUtilization.test.tsx.snap b/packages/react-charts/src/victory/components/ChartDonutUtilization/__snapshots__/ChartDonutUtilization.test.tsx.snap new file mode 100644 index 00000000000..6836ecc4ea9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/__snapshots__/ChartDonutUtilization.test.tsx.snap @@ -0,0 +1,133 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartDonutUtilization 1`] = ` + +
    + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartDonutUtilization 2`] = ` + +
    + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartDonutUtilization.md b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartDonutUtilization.md new file mode 100644 index 00000000000..be17f8b9589 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartDonutUtilization.md @@ -0,0 +1,129 @@ +--- +id: Donut utilization chart +section: components +subsection: charts +propComponents: [ + 'ChartDonutThreshold', + 'ChartDonutUtilization' +] +hideDarkMode: true +--- + +import { ChartDonutThreshold, ChartDonutUtilization, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Donut utilization examples +### Basic +```ts file = "ChartUtilBasic.tsx" + +``` + +### Right aligned legend +```ts file = "ChartUtilRightAlignedLegend.tsx" + +``` + +### Inverted with right aligned legend +```ts file = "ChartUtilInvertedRightLegend.tsx" + +``` + +### Right aligned vertical legend +```ts file = "ChartUtilRightVerticalLegend.tsx" + +``` + +### Bottom aligned legend +```ts file = "ChartUtilBottomAlignedLegend.tsx" + +``` + +### Small +```ts file = "ChartUtilSmall.tsx" + +``` + +### Small with right aligned legend +```ts file = "ChartUtilSmallRightLegend.tsx" + +``` + +### Small with bottom aligned subtitle + +This is a small donut utilization chart with bottom aligned legend and right aligned subtitle. + +```ts file = "ChartUtilSmallBottomSubtitle.tsx" + +``` + +### Small with right aligned subtitle +```ts file = "ChartUtilSmallRightSubtitle.tsx" + +``` + +## Donut utilization threshold examples +### Static thresholds +```ts file = "ChartUtilStatic.tsx" + +``` + +### Static thresholds with right aligned legend +```ts file = "ChartUtilStaticRightLegend.tsx" + +``` + +### Inverted static thresholds with right aligned legend +```ts file = "ChartUtilInvertedStatic.tsx" + +``` + +### Static thresholds with custom legend +```ts file = "ChartUtilStaticCustomLegend.tsx" + +``` + +### Static thresholds with bottom aligned legend +```ts file = "ChartUtilStaticBottomLegend.tsx" + +``` + +### Small with static thresholds +```ts file = "ChartUtilSmallStatic.tsx" + +``` + +### Small with static thresholds and right aligned legend +```ts file = "ChartUtilSmallStaticRightLegend.tsx" + +``` + +### Small with subtitle + +This is a small donut utilization chart with static thresholds with right aligned legend and bottom aligned subtitle. + +```ts file = "ChartUtilSmallSubtitle.tsx" + +``` + +### Small with thresholds and right aligned subtitle +```ts file = "ChartUtilSmallRightAlignedSubtitle.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `ChartDonutThreshold` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartDonutUtilization` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilBasic.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilBasic.tsx new file mode 100644 index 00000000000..56391d8cbd5 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilBasic.tsx @@ -0,0 +1,25 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x: string; + y: number; +} + +export const ChartUtilBasic: React.FunctionComponent = () => { + const data: UsageData = { x: 'GBps capacity', y: 75 }; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + name="chart1" + subTitle="of 100 GBps" + title="75%" + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilBottomAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilBottomAlignedLegend.tsx new file mode 100644 index 00000000000..0461a403c9b --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilBottomAlignedLegend.tsx @@ -0,0 +1,38 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilBottomAlignedLegend: React.FunctionComponent = () => { + const data: UsageData = { x: 'Storage capacity', y: 45 }; + const legendData: UsageData[] = [{ name: `Storage capacity: 45%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendPosition="bottom" + name="chart5" + padding={{ + bottom: 65, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + subTitle="of 100 GBps" + title="45%" + thresholds={[{ value: 60 }, { value: 90 }]} + width={300} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilInvertedRightLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilInvertedRightLegend.tsx new file mode 100644 index 00000000000..193a931da4a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilInvertedRightLegend.tsx @@ -0,0 +1,54 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilInvertedRightLegend: React.FunctionComponent = () => { + const [spacer, setSpacer] = useState(''); + const [used, setUsed] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (((prevUsed - 10) % 100) + 100) % 100; + setSpacer(val < 10 ? ' ' : ''); + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const data: UsageData = { x: 'GBps capacity', y: used }; + const legendData: UsageData[] = [{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + name="chart3" + padding={{ + bottom: 20, + left: 20, + right: 225, // Adjusted to accommodate legend + top: 20 + }} + subTitle="of 100 GBps" + title={`${used}%`} + thresholds={[{ value: 60 }, { value: 20 }]} + width={435} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilInvertedStatic.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilInvertedStatic.tsx new file mode 100644 index 00000000000..a72f7ef05e3 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilInvertedStatic.tsx @@ -0,0 +1,65 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilInvertedStatic: React.FunctionComponent = () => { + const [used, setUsed] = useState(100); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (prevUsed - 10 + 100) % 100; + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 20%', y: 20 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: used }; + const legendData: UsageData[] = [ + { name: `Storage capacity: ${used}%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 20%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart12" + padding={{ + bottom: 20, + left: 20, + right: 290, // Adjusted to accommodate legend + top: 20 + }} + width={500} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + subTitle="of 100 GBps" + title={`${used}%`} + thresholds={[{ value: 60 }, { value: 20 }]} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilRightAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilRightAlignedLegend.tsx new file mode 100644 index 00000000000..e21b6597f81 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilRightAlignedLegend.tsx @@ -0,0 +1,53 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilRightAlignedLegend: React.FunctionComponent = () => { + const [spacer, setSpacer] = useState(''); + const [used, setUsed] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (prevUsed + 10) % 100; + setSpacer(val < 10 ? ' ' : ''); + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const data: UsageData = { x: 'GBps capacity', y: used }; + const legendData: UsageData[] = [{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + name="chart2" + padding={{ + bottom: 20, + left: 20, + right: 225, // Adjusted to accommodate legend + top: 20 + }} + subTitle="of 100 GBps" + title={`${used}%`} + thresholds={[{ value: 60 }, { value: 90 }]} + width={435} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilRightVerticalLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilRightVerticalLegend.tsx new file mode 100644 index 00000000000..76626ce71b9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilRightVerticalLegend.tsx @@ -0,0 +1,56 @@ +import { ChartDonutUtilization, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilRightVerticalLegend: React.FunctionComponent = () => { + const [spacer, setSpacer] = useState(''); + const [used, setUsed] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (prevUsed + 10) % 100; + setSpacer(val < 10 ? ' ' : ''); + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const data: UsageData = { x: 'Storage capacity', y: used }; + const legendData: UsageData[] = [{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + legendPosition="bottom" + name="chart4" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + subTitle="of 100 GBps" + title={`${used}%`} + themeColor={ChartThemeColor.green} + thresholds={[{ value: 60 }, { value: 90 }]} + width={230} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmall.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmall.tsx new file mode 100644 index 00000000000..f9a50c298ff --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmall.tsx @@ -0,0 +1,26 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x: string; + y: number; +} + +export const ChartUtilSmall: React.FunctionComponent = () => { + const data: UsageData = { x: 'Storage capacity', y: 75 }; + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + name="chart6" + subTitle="of 100 GBps" + title="75%" + width={175} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallBottomSubtitle.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallBottomSubtitle.tsx new file mode 100644 index 00000000000..ebd0008949a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallBottomSubtitle.tsx @@ -0,0 +1,39 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilSmallBottomSubtitle: React.FunctionComponent = () => { + const data: UsageData = { x: 'Storage capacity', y: 45 }; + const legendData: UsageData[] = [{ name: `Storage capacity: 45%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + name="chart8" + padding={{ + bottom: 25, // Adjusted to accommodate subTitle + left: 20, + right: 195, // Adjusted to accommodate legend + top: 20 + }} + subTitle="of 100 GBps" + subTitlePosition="bottom" + title="45%" + thresholds={[{ value: 60 }, { value: 90 }]} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightAlignedSubtitle.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightAlignedSubtitle.tsx new file mode 100644 index 00000000000..ee21d72ffdc --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightAlignedSubtitle.tsx @@ -0,0 +1,52 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilSmallRightAlignedSubtitle: React.FunctionComponent = () => { + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: 45 }; + const legendData: UsageData[] = [ + { name: `Storage capacity: 45%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 90%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart18" + padding={{ + bottom: 60, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + subTitlePosition="right" + width={675} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendPosition="bottom" + subTitle="of 100 GBps" + title="45%" + thresholds={[{ value: 60 }, { value: 90 }]} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightLegend.tsx new file mode 100644 index 00000000000..78eb2ddd1b3 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightLegend.tsx @@ -0,0 +1,54 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilSmallRightLegend: React.FunctionComponent = () => { + const [spacer, setSpacer] = useState(''); + const [used, setUsed] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (prevUsed + 10) % 100; + setSpacer(val < 10 ? ' ' : ''); + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const data: UsageData = { x: 'Storage capacity', y: used }; + const legendData: UsageData[] = [{ name: `Storage capacity: ${spacer}${used}%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + name="chart7" + padding={{ + bottom: 20, + left: 20, + right: 195, // Adjusted to accommodate legend + top: 20 + }} + subTitle="of 100 GBps" + title={`${used}%`} + thresholds={[{ value: 60 }, { value: 90 }]} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightSubtitle.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightSubtitle.tsx new file mode 100644 index 00000000000..723d517a4e0 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallRightSubtitle.tsx @@ -0,0 +1,39 @@ +import { ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilSmallRightSubtitle: React.FunctionComponent = () => { + const data: UsageData = { x: 'Storage capacity', y: 45 }; + const legendData: UsageData[] = [{ name: `Storage capacity: 45%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendPosition="bottom" + name="chart9" + padding={{ + bottom: 45, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + subTitle="of 100 GBps" + subTitlePosition="right" + title="45%" + thresholds={[{ value: 60 }, { value: 90 }]} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallStatic.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallStatic.tsx new file mode 100644 index 00000000000..d8dced1e8b7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallStatic.tsx @@ -0,0 +1,36 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x: string; + y: number; +} + +export const ChartUtilSmallStatic: React.FunctionComponent = () => { + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: 45 }; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart15" + width={185} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + subTitle="of 100 GBps" + title="45%" + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallStaticRightLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallStaticRightLegend.tsx new file mode 100644 index 00000000000..7e88687558c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallStaticRightLegend.tsx @@ -0,0 +1,65 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilSmallStaticRightLegend: React.FunctionComponent = () => { + const [used, setUsed] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (prevUsed + 10) % 100; + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: used }; + const legendData: UsageData[] = [ + { name: `Storage capacity: ${used}%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 90%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart16" + padding={{ + bottom: 20, + left: 20, + right: 260, // Adjusted to accommodate legend + top: 20 + }} + width={425} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + subTitle="of 100 GBps" + title={`${used}%`} + thresholds={[{ value: 60 }, { value: 90 }]} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallSubtitle.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallSubtitle.tsx new file mode 100644 index 00000000000..04474836897 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilSmallSubtitle.tsx @@ -0,0 +1,52 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilSmallSubtitle: React.FunctionComponent = () => { + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: 45 }; + const legendData: UsageData[] = [ + { name: `Storage capacity: 45%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 90%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart17" + padding={{ + bottom: 30, // Adjusted to accommodate label + left: 20, + right: 260, // Adjusted to accommodate legend + top: 20 + }} + subTitlePosition="bottom" + width={425} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + subTitle="of 100 GBps" + title="45%" + thresholds={[{ value: 60 }, { value: 90 }]} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStatic.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStatic.tsx new file mode 100644 index 00000000000..09faef161fd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStatic.tsx @@ -0,0 +1,34 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x: string; + y: number; +} + +export const ChartUtilStatic: React.FunctionComponent = () => { + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: 45 }; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart10" + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + subTitle="of 100 GBps" + title="45%" + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticBottomLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticBottomLegend.tsx new file mode 100644 index 00000000000..250c2048145 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticBottomLegend.tsx @@ -0,0 +1,50 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilStaticBottomLegend: React.FunctionComponent = () => { + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: 45 }; + const legendData: UsageData[] = [ + { name: `Storage capacity: 45%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 90%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart14" + padding={{ + bottom: 65, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + width={675} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendPosition="bottom" + subTitle="of 100 GBps" + title="45%" + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticCustomLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticCustomLegend.tsx new file mode 100644 index 00000000000..b6d3ada2ce8 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticCustomLegend.tsx @@ -0,0 +1,67 @@ +import { ChartDonutThreshold, ChartDonutUtilization, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilStaticCustomLegend: React.FunctionComponent = () => { + const [used, setUsed] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (prevUsed + 10) % 100; + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: used }; + const legendData: UsageData[] = [ + { name: `Storage capacity: ${used}%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 90%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart13" + padding={{ + bottom: 125, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + width={230} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + legendPosition="bottom" + subTitle="of 100 GBps" + title={`${used}%`} + themeColor={ChartThemeColor.green} + thresholds={[{ value: 60 }, { value: 90 }]} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticRightLegend.tsx b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticRightLegend.tsx new file mode 100644 index 00000000000..57a1a6db5c0 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartDonutUtilization/examples/ChartUtilStaticRightLegend.tsx @@ -0,0 +1,64 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; +import { useEffect, useState } from 'react'; + +interface UsageData { + x?: string; + y?: number; + name?: string; +} + +export const ChartUtilStaticRightLegend: React.FunctionComponent = () => { + const [used, setUsed] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setUsed((prevUsed) => { + const val = (prevUsed + 10) % 100; + return val; + }); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const dataThreshold: UsageData[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const dataUtil: UsageData = { x: 'Storage capacity', y: used }; + const legendData: UsageData[] = [ + { name: `Storage capacity: ${used}%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 90%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart11" + padding={{ + bottom: 20, + left: 20, + right: 290, // Adjusted to accommodate legend + top: 20 + }} + width={500} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + subTitle="of 100 GBps" + title={`${used}%`} + thresholds={[{ value: 60 }, { value: 90 }]} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartGroup/ChartGroup.test.tsx b/packages/react-charts/src/victory/components/ChartGroup/ChartGroup.test.tsx new file mode 100644 index 00000000000..5d3c972ff67 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartGroup/ChartGroup.test.tsx @@ -0,0 +1,35 @@ +import { render } from '@testing-library/react'; +import { ChartArea } from '../ChartArea/ChartArea'; +import { ChartGroup } from './ChartGroup'; + +Object.values([true, false]).forEach(() => { + test('ChartGroup', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders container children', () => { + const { asFragment } = render( + + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartGroup/ChartGroup.tsx b/packages/react-charts/src/victory/components/ChartGroup/ChartGroup.tsx similarity index 84% rename from packages/react-charts/src/components/ChartGroup/ChartGroup.tsx rename to packages/react-charts/src/victory/components/ChartGroup/ChartGroup.tsx index 17a64e285ec..a92b3c0eadf 100644 --- a/packages/react-charts/src/components/ChartGroup/ChartGroup.tsx +++ b/packages/react-charts/src/victory/components/ChartGroup/ChartGroup.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -19,18 +19,21 @@ import { VictoryStyleInterface } from 'victory-core'; import { VictoryGroup, VictoryGroupProps, VictoryGroupTTargetType } from 'victory-group'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getClassName, getTheme } from '../ChartUtils'; - -export enum ChartGroupSortOrder { - ascending = 'ascending', - descending = 'descending' -} +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getClassName } from '../ChartUtils/chart-helpers'; +import { useDefaultPatternProps, getPatternDefs, renderChildrenWithPatterns } from '../ChartUtils/chart-patterns'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-group/src/index.d.ts + * ChartGroup is a wrapper component that renders a given set of children with some shared props. ChartGroup reconciles + * the domain and layout for all its children, and coordinates animations and shared events. ChartGroup may also be used + * to supply common data and styles to all its children. This is especially useful when adding markers to a line, or + * adding voronoi tooltips to data. ChartGroup may also be used to apply an offset to a group of children, as with + * grouped bar charts, or may be used to stack several components on the same level, e.g., stacked area charts with + * data markers. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-group/src/index.d.ts */ export interface ChartGroupProps extends VictoryGroupProps { /** @@ -149,7 +152,7 @@ export interface ChartGroupProps extends VictoryGroupProps { * Since ChartGroup only renders a single element, the eventKey property is not used. * The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -194,6 +197,19 @@ export interface ChartGroupProps extends VictoryGroupProps { * to a tag on web, and a react-native-svg tag on mobile */ groupComponent?: React.ReactElement; + /** + * The hasPatterns prop is an optional prop that indicates whether a pattern is shown for a chart. + * SVG patterns are dynamically generated (unique to each chart) in order to apply colors from the selected + * color theme or custom color scale. Those generated patterns are applied in a specific order (via a URL), similar + * to the color theme ordering defined by PatternFly. If the multi-color theme was in use; for example, colorized + * patterns would be displayed in that same order. Create custom patterns via the patternScale prop. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example hasPatterns={ true } + * @example hasPatterns={[ true, true, false ]} + */ + hasPatterns?: boolean | boolean[]; /** * The height props specifies the height the svg viewBox of the chart container. * This value should be given as a number of pixels @@ -232,7 +248,7 @@ export interface ChartGroupProps extends VictoryGroupProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -247,7 +263,7 @@ export interface ChartGroupProps extends VictoryGroupProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -285,6 +301,16 @@ export interface ChartGroupProps extends VictoryGroupProps { * @propType number | { top: number, bottom: number, left: number, right: number } */ padding?: PaddingProps; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; /** * Victory components can pass a boolean polar prop to specify whether a label is part of a polar chart. */ @@ -329,6 +355,7 @@ export interface ChartGroupProps extends VictoryGroupProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -340,7 +367,7 @@ export interface ChartGroupProps extends VictoryGroupProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -395,14 +422,6 @@ export interface ChartGroupProps extends VictoryGroupProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -449,17 +468,18 @@ export const ChartGroup: React.FunctionComponent = ({ ariaDesc, ariaTitle, children, + colorScale, containerComponent = , + hasPatterns, + patternScale, themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), - + theme = getTheme(themeColor), ...rest }: ChartGroupProps) => { // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { desc: ariaDesc, title: ariaTitle, theme, @@ -467,10 +487,22 @@ export const ChartGroup: React.FunctionComponent = ({ className: getClassName({ className: containerComponent.props.className }) // Override VictoryContainer class name }); + const { defaultColorScale, defaultPatternScale, isPatternDefs, patternId } = useDefaultPatternProps({ + colorScale, + hasPatterns, + patternScale, + themeColorScale: theme.group.colorScale as string[] + }); + // Note: containerComponent is required for theme return ( - - {children} + + {renderChildrenWithPatterns({ + children, + patternScale: defaultPatternScale, + themeColor + })} + {isPatternDefs && getPatternDefs({ patternId, colorScale: defaultColorScale })} ); }; diff --git a/packages/react-charts/src/victory/components/ChartGroup/__snapshots__/ChartGroup.test.tsx.snap b/packages/react-charts/src/victory/components/ChartGroup/__snapshots__/ChartGroup.test.tsx.snap new file mode 100644 index 00000000000..afe49088662 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartGroup/__snapshots__/ChartGroup.test.tsx.snap @@ -0,0 +1,131 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartGroup 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartGroup 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders container children 1`] = ` + +
    + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartLabel/ChartLabel.test.tsx b/packages/react-charts/src/victory/components/ChartLabel/ChartLabel.test.tsx new file mode 100644 index 00000000000..1f9e3f3b461 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLabel/ChartLabel.test.tsx @@ -0,0 +1,14 @@ +import { render } from '@testing-library/react'; +import { ChartLabel } from './ChartLabel'; + +Object.values([true, false]).forEach(() => { + test('ChartLabel', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component text', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartLabel/ChartLabel.tsx b/packages/react-charts/src/victory/components/ChartLabel/ChartLabel.tsx similarity index 89% rename from packages/react-charts/src/components/ChartLabel/ChartLabel.tsx rename to packages/react-charts/src/victory/components/ChartLabel/ChartLabel.tsx index ff8a1dee38c..a150694ca73 100644 --- a/packages/react-charts/src/components/ChartLabel/ChartLabel.tsx +++ b/packages/react-charts/src/victory/components/ChartLabel/ChartLabel.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import defaults from 'lodash/defaults'; import { @@ -10,22 +9,12 @@ import { VictoryLabel, VictoryLabelProps } from 'victory-core'; -import { ChartCommonStyles } from '../ChartTheme'; - -export enum ChartLabelDirection { - rtl = 'rtl', - ltr = 'ltr', - inherit = 'inherit' -} - -export enum ChartLabelPlacement { - parallel = 'parallel', - perpendicular = 'perpendicular', - vertical = 'vertical' -} +import { ChartCommonStyles } from '../ChartTheme/ChartStyles'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts + * ChartLabel renders the label components that are used across all Victory based components. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-core/src/victory-label/victory-label.tsx */ export interface ChartLabelProps extends VictoryLabelProps { /** @@ -54,6 +43,8 @@ export interface ChartLabelProps extends VictoryLabelProps { * Note: This prop should not be set manually. * * @propType number | string | Function + * + * @private Not intended as public API and subject to change * @hide */ children?: StringOrNumberOrCallback; @@ -62,7 +53,7 @@ export interface ChartLabelProps extends VictoryLabelProps { */ className?: string; /** - * Labels that apply to an entire data series will recieve the entire series as `data` instead of an individual datum + * Labels that apply to an entire data series will receive the entire series as `data` instead of an individual datum * prop. */ data?: any[]; @@ -98,11 +89,16 @@ export interface ChartLabelProps extends VictoryLabelProps { * Event handlers are currently only called with their corresponding events. */ events?: React.DOMAttributes; + /** + * The id prop specifies a HTML ID that will be applied to the rendered text element. + */ + id?: StringOrNumberOrCallback; /** * The index prop represents the index of the datum in the data array. * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ index?: string | number; @@ -114,7 +110,7 @@ export interface ChartLabelProps extends VictoryLabelProps { /** * The labelPlacement prop is used to specify the placement of labels relative to the data point they represent. * This prop may be given as “vertical”, “parallel” or “perpendicular”. This props is particularly useful in polar - * charts, where it may be desireable to position a label either parallel or perpendicular to its corresponding angle. + * charts, where it may be desirable to position a label either parallel or perpendicular to its corresponding angle. * When this prop is not set, perpendicular label placement will be used for polar charts, and vertical label * placement will be used for cartesian charts. * @@ -144,6 +140,7 @@ export interface ChartLabelProps extends VictoryLabelProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -158,6 +155,7 @@ export interface ChartLabelProps extends VictoryLabelProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ scale?: { x?: any; y?: any }; @@ -199,6 +197,7 @@ export interface ChartLabelProps extends VictoryLabelProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ width?: number; @@ -224,6 +223,7 @@ export const ChartLabel: React.FunctionComponent = ({ textAnchor // textAnchor prop must override given theme styles }, { + fill: ChartCommonStyles.label.fill, fontFamily: ChartCommonStyles.label.fontFamily, fontSize: ChartCommonStyles.label.fontSize, letterSpacing: ChartCommonStyles.label.letterSpacing diff --git a/packages/react-charts/src/victory/components/ChartLabel/__snapshots__/ChartLabel.test.tsx.snap b/packages/react-charts/src/victory/components/ChartLabel/__snapshots__/ChartLabel.test.tsx.snap new file mode 100644 index 00000000000..3703c9eebb0 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLabel/__snapshots__/ChartLabel.test.tsx.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartLabel 1`] = ``; + +exports[`ChartLabel 2`] = ``; + +exports[`renders component text 1`] = ` + + + + This is a test + + + +`; diff --git a/packages/react-charts/src/victory/components/ChartLegend/ChartLegend.test.tsx b/packages/react-charts/src/victory/components/ChartLegend/ChartLegend.test.tsx new file mode 100644 index 00000000000..9f42835b0c6 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/ChartLegend.test.tsx @@ -0,0 +1,26 @@ +import { render } from '@testing-library/react'; +import { ChartLegend } from './ChartLegend'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; + +Object.values([true, false]).forEach(() => { + test('ChartLegend', () => { + const { asFragment } = render( + } labelComponent={} /> + ); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + } + labelComponent={} + /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartLegend/ChartLegend.tsx b/packages/react-charts/src/victory/components/ChartLegend/ChartLegend.tsx similarity index 78% rename from packages/react-charts/src/components/ChartLegend/ChartLegend.tsx rename to packages/react-charts/src/victory/components/ChartLegend/ChartLegend.tsx index 20259d72d46..03efdd8302e 100644 --- a/packages/react-charts/src/components/ChartLegend/ChartLegend.tsx +++ b/packages/react-charts/src/victory/components/ChartLegend/ChartLegend.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { BlockProps, @@ -17,31 +17,16 @@ import { VictoryLegendOrientationType, VictoryLegendTTargetType } from 'victory-legend'; -import { ChartContainer } from '../ChartContainer'; -import { ChartLabel } from '../ChartLabel'; -import { ChartPoint } from '../ChartPoint'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getTheme } from '../ChartUtils'; - -export enum ChartLegendOrientation { - horizontal = 'horizontal', - vertical = 'vertical' -} - -export enum ChartLegendPosition { - bottom = 'bottom', - bottomLeft = 'bottom-left', - right = 'right' -} - -export enum ChartLegendRowGutter { - bottom = 'bottom', - top = 'top' -} +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartPoint } from '../ChartPoint/ChartPoint'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getComponentTheme, getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and See https://github.com/FormidableLabs/victory/blob/master/packages/victory-legend/src/index.d.ts + * ChartLegend renders a chart legend component. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-legend/src/index.d.ts */ export interface ChartLegendProps extends VictoryLegendProps { /** @@ -60,7 +45,7 @@ export interface ChartLegendProps extends VictoryLegendProps { /** * The borderPadding specifies the amount of padding that should * be added between the legend items and the border. This prop may be given as - * a number, or asanobject with values specified for top, bottom, left, and right. + * a number, or as an object with values specified for top, bottom, left, and right. * Please note that the default width and height calculated for the border * component is based on approximated text measurements, so padding may need to be adjusted. * @@ -154,15 +139,6 @@ export interface ChartLegendProps extends VictoryLegendProps { * are the space between rows. */ gutter?: number | { left: number; right: number }; - /** - * Specifies the height the svg viewBox of the chart container. This value should be given as a - * number of pixels. - * - * Because Victory renders responsive containers, the width and height props do not determine the width and - * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of - * pixels will depend on the size of the container the chart is rendered into. - */ - height?: number; /** * The itemsPerRow prop determines how many items to render in each row * of a horizontal legend, or in each column of a vertical legend. This @@ -180,6 +156,12 @@ export interface ChartLegendProps extends VictoryLegendProps { * ChartLabel will be created with the props described above. */ labelComponent?: React.ReactElement; + /** + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. + */ + name?: string; /** * The orientation prop takes a string that defines whether legend data * are displayed in a row or column. When orientation is "horizontal", @@ -201,6 +183,16 @@ export interface ChartLegendProps extends VictoryLegendProps { * @propType number | { top: number, bottom: number, left: number, right: number } */ padding?: PaddingProps; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; /** * The responsive prop specifies whether the rendered container should be a responsive container with a viewBox * attribute, or a static container with absolute width and height. @@ -225,6 +217,7 @@ export interface ChartLegendProps extends VictoryLegendProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -266,14 +259,6 @@ export interface ChartLegendProps extends VictoryLegendProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title prop specifies a title to render with the legend. * This prop should be given as a string, or an array of strings for multi-line titles. @@ -281,8 +266,8 @@ export interface ChartLegendProps extends VictoryLegendProps { title?: string | string[]; /** * The titleComponent prop takes a component instance which will be used to render - * a title for the component. The new element created from the passed - * labelComponent will be supplied with the following properties: x, y, index, data, + * a title for the component. The new element created from the passed label + * component will be supplied with the following properties: x, y, index, data, * datum, verticalAnchor, textAnchor, style, text, and events. Any of these props * may be overridden by passing in props to the supplied component, or modified * or ignored within the custom component itself. If labelComponent is omitted, @@ -290,7 +275,7 @@ export interface ChartLegendProps extends VictoryLegendProps { */ titleComponent?: React.ReactElement; /** - * The titleOrientation prop specifies where the a title should be rendered + * The titleOrientation prop specifies where the title should be rendered * in relation to the rest of the legend. Possible values * for this prop are “top”, “bottom”, “left”, and “right”. * @@ -317,33 +302,79 @@ export interface ChartLegendProps extends VictoryLegendProps { } export const ChartLegend: React.FunctionComponent = ({ + colorScale, containerComponent = , dataComponent = , labelComponent = , + name, + patternScale, responsive = true, + style, themeColor, - themeVariant, titleComponent = , // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartLegendProps) => { + const componentTheme = getComponentTheme(themeColor); + + // Merge pattern IDs with `style.data.fill` property + const getDefaultStyle = () => { + if (!patternScale) { + return style; + } + + // Note: ChartLegendTooltipContent overrides patterns via `data.symbol.fill` property + const _style = style ? { ...style } : {}; + _style.data = { + fill: ({ index }: any) => { + const themeColor = + theme && theme.legend && theme.legend.colorScale + ? theme.legend.colorScale[index % theme.legend.colorScale.length] + : undefined; + const color = colorScale ? colorScale[index % colorScale.length] : themeColor; // Sync color scale + const pattern = patternScale[index % patternScale.length]; + return pattern ? pattern : color; + }, + ..._style.data + }; + return _style; + }; + // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { responsive, theme, ...containerComponent.props }); + const getLabelComponent = () => + cloneElement(labelComponent, { + ...(name && { id: (props: any) => `${name}-${(labelComponent as any).type.displayName}-${props.index}` }), + ...labelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle + }); + + const getTitleComponent = () => + cloneElement(titleComponent, { + // Victory doesn't appear to call the id function here, but it's valid for label components + ...(name && { id: () => `${name}-${(titleComponent as any).type.displayName}` }), + ...titleComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle + }); + // Note: containerComponent is required for theme return ( ); @@ -354,7 +385,8 @@ ChartLegend.displayName = 'ChartLegend'; hoistNonReactStatics(ChartLegend, VictoryLegend, { getBaseProps: true }); (ChartLegend as any).getBaseProps = (props: any) => { - const theme = getTheme(null, null); + const theme = getTheme(null); + return (VictoryLegend as any).getBaseProps( { titleComponent: , // Workaround for getBaseProps error diff --git a/packages/react-charts/src/victory/components/ChartLegend/__snapshots__/ChartLegend.test.tsx.snap b/packages/react-charts/src/victory/components/ChartLegend/__snapshots__/ChartLegend.test.tsx.snap new file mode 100644 index 00000000000..bd9a91ce07a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/__snapshots__/ChartLegend.test.tsx.snap @@ -0,0 +1,294 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartLegend 1`] = ` + +
    + + + + + + + Series 1 + + + + + Series 2 + + + +
    + +
    +
    +
    +`; + +exports[`ChartLegend 2`] = ` + +
    + + + + + + + Series 1 + + + + + Series 2 + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + Average number of pets + + + + + Cats + + + + + Dogs + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegend.md b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegend.md new file mode 100644 index 00000000000..cbfe8f07204 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegend.md @@ -0,0 +1,143 @@ +--- +id: Legends +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartArea', + 'ChartAxis', + 'ChartBar', + 'ChartBullet', + 'ChartDonut', + 'ChartGroup', + 'ChartLabel', + 'ChartLegend', + 'ChartLegendTooltip', + 'ChartLine', + 'ChartPie', + 'ChartScatter', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { cloneElement, useEffect, useRef, useState } from 'react'; +import { + Chart, + ChartArea, + ChartAxis, + ChartBar, + ChartBullet, + ChartContainer, + ChartDonut, + ChartGroup, + ChartLabel, + ChartLegend, + ChartLegendTooltip, + ChartLine, + ChartPie, + ChartScatter, + ChartThemeColor, + ChartVoronoiContainer, + createContainer, + getInteractiveLegendEvents, + getInteractiveLegendItemStyles +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; +import '@patternfly/patternfly/patternfly-charts.css'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic with right aligned legend +```ts file = "ChartLegendBasicRightLegend.tsx" + +``` + +### Bottom aligned legend +```ts file = "ChartLegendBottomAlignedLegend.tsx" + +``` + +### Responsive bottom-left aligned legend + +This demonstrates a responsive legend which wraps when items are wider than its container. + +```ts file = "ChartLegendResponsiveBottomLeft.tsx" + +``` + +### Standalone legend + +This demonstrates a standalone legend vs. using the `legendData` property. + +```ts file = "ChartLegendStandalone.tsx" + +``` + +### Interactive legend + +This demonstrates how to add an interactive legend using events such as `onMouseOver`, `onMouseOut`, and `onClick`. + +```ts file = "ChartLegendInteractive.tsx" + +``` + +### Interactive legend with pie chart + +This demonstrates how to add an interactive legend to a pie chart using events such as `onMouseOver`, `onMouseOut`, and `onClick`. + +```ts file = "ChartLegendInteractivePieChart.tsx" + +``` + +### Legend tooltips + +This demonstrates an approach for applying tooltips to a legend using a custom label component. These tooltips are keyboard navigable. + +```ts file = "ChartLegendTooltips.tsx" + +``` + +### Legend links + +This demonstrates an approach for applying links to a legend using a custom label component. These links are keyboard navigable. + +```ts file = "ChartLegendLinks.tsx" + +``` + +### Legend layout + +This demonstrates an approach for applying a different legend layout and styles using a custom label component. + +```ts file = "ChartLegendLayout.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartBullet` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartDonut` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartLabel` props, see [VictoryLabel](https://formidable.com/open-source/victory/docs/victory-label) +- For `ChartLegend` props, see [VictoryLegend](https://formidable.com/open-source/victory/docs/victory-legend) +- For `ChartLine` props, see [VictoryLine](https://formidable.com/open-source/victory/docs/victory-line) +- For `ChartPie` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartScatter` props, see [VictoryScatter](https://formidable.com/open-source/victory/docs/victory-scatter) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendBasicRightLegend.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendBasicRightLegend.tsx new file mode 100644 index 00000000000..1ebb5a2c0a0 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendBasicRightLegend.tsx @@ -0,0 +1,41 @@ +import { ChartDonut } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartLegendBasicRightLegend: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart1" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + title="100" + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendBottomAlignedLegend.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendBottomAlignedLegend.tsx new file mode 100644 index 00000000000..5b9f412340a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendBottomAlignedLegend.tsx @@ -0,0 +1,76 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartGroup, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartLegendBottomAlignedLegend: React.FunctionComponent = () => { + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendPosition="bottom" + height={275} + name="chart2" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.purple} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendInteractive.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendInteractive.tsx new file mode 100644 index 00000000000..1cca049d777 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendInteractive.tsx @@ -0,0 +1,154 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartLegend, + ChartLegendTooltip, + ChartScatter, + ChartThemeColor, + createContainer, + getInteractiveLegendEvents, + getInteractiveLegendItemStyles +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useRef, useState, useEffect } from 'react'; + +export const ChartLegendInteractive: React.FunctionComponent = () => { + const containerRef = useRef(null); + const [hiddenSeries, setHiddenSeries] = useState(new Set()); + const [width, setWidth] = useState(0); + + const series = [ + { + datapoints: [ + { x: '2015', y: 3 }, + { x: '2016', y: 4 }, + { x: '2017', y: 8 }, + { x: '2018', y: 6 } + ], + legendItem: { name: 'Cats' } + }, + { + datapoints: [ + { x: '2015', y: 2 }, + { x: '2016', y: 3 }, + { x: '2017', y: 4 }, + { x: '2018', y: 5 }, + { x: '2019', y: 6 } + ], + legendItem: { name: 'Dogs' } + }, + { + datapoints: [ + { x: '2015', y: 1 }, + { x: '2016', y: 2 }, + { x: '2017', y: 3 }, + { x: '2018', y: 2 }, + { x: '2019', y: 4 } + ], + legendItem: { name: 'Birds' } + } + ]; + + // Returns groups of chart names associated with each data series + const getChartNames = () => series.map((_, index) => [`area-${index}`, `scatter-${index}`]); + + // Handles legend click to toggle visibility of data series + const handleLegendClick = (props) => { + setHiddenSeries((prev) => { + const newHidden = new Set(prev); + if (!newHidden.delete(props.index)) { + newHidden.add(props.index); + } + return newHidden; + }); + }; + + // Returns legend data styled per hiddenSeries + const getLegendData = () => + series.map((s, index) => ({ + childName: `area-${index}`, + ...s.legendItem, + ...getInteractiveLegendItemStyles(hiddenSeries.has(index)) + })); + + // Returns true if data series is hidden + const isHidden = (index) => hiddenSeries.has(index); + + // Checks if any data series is visible + const isDataAvailable = () => hiddenSeries.size !== series.length; + + // Set chart width per current window size + useEffect(() => { + const observer = getResizeObserver(containerRef.current, () => { + if (containerRef.current?.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }); + return () => observer(); + }, []); + + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const container = ( + (datum.childName.includes('area-') && datum.y !== null ? `${datum.y}` : null)} + labelComponent={ datum.x} />} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + disable={!isDataAvailable()} + /> + ); + + return ( +
    +
    + } + legendPosition="bottom-left" + name="chart5" + padding={{ bottom: 75, left: 50, right: 50, top: 50 }} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + {series.map((s, index) => ( + (active ? 5 : 3)} + /> + ))} + + + {series.map((s, index) => ( + + ))} + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendInteractivePieChart.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendInteractivePieChart.tsx new file mode 100644 index 00000000000..8729019333e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendInteractivePieChart.tsx @@ -0,0 +1,95 @@ +import { + Chart, + ChartLegend, + ChartThemeColor, + ChartPie, + getInteractiveLegendEvents, + getInteractiveLegendItemStyles +} from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +export const ChartLegendInteractivePieChart: React.FunctionComponent = () => { + const [hiddenSeries, setHiddenSeries] = useState>(new Set()); + + const series = [ + { + datapoints: { x: 'Cats', y: 35 }, + legendItem: { name: 'Cats: 35' } + }, + { + datapoints: { x: 'Dogs', y: 55 }, + legendItem: { name: 'Dogs: 55' } + }, + { + datapoints: { x: 'Birds', y: 10 }, + legendItem: { name: 'Birds: 10' } + } + ]; + + // Returns groups of chart names associated with each data series + const getChartNames = () => { + const result = []; + series.map((_, _index) => { + // Provide names for each series hidden / shown -- use the same name for a pie chart + result.push(['pie']); + }); + return result; + }; + + // Returns legend data styled per hiddenSeries + const getLegendData = () => + series.map((s, index) => ({ + ...s.legendItem, // name property + ...getInteractiveLegendItemStyles(hiddenSeries.has(index)) // hidden styles + })); + + // Hide each data series individually + const handleLegendClick = (props: { index: number }) => { + const newHiddenSeries = new Set(hiddenSeries); + if (newHiddenSeries.delete(props.index)) { + newHiddenSeries.add(props.index); + } + setHiddenSeries(newHiddenSeries); + }; + + // Returns true if data series is hidden + const isHidden = (index: number) => hiddenSeries.has(index); + // Returns onMouseOver, onMouseOut, and onClick events for the interactive legend + const getEvents = () => + getInteractiveLegendEvents({ + chartNames: getChartNames(), + isHidden, + legendName: 'chart6-ChartLegend', + onLegendClick: handleLegendClick + }); + + const data = []; + series.map((s, index) => { + data.push(!hiddenSeries.has(index) ? s.datapoints : { y: null }); + }); + + return ( +
    + } + legendPosition="bottom" + name="chart6" + padding={{ + bottom: 65, + left: 20, + right: 20, + top: 20 + }} + showAxis={false} + themeColor={ChartThemeColor.multiUnordered} + width={300} + > + `${datum.x}: ${datum.y}`} name="pie" /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendLayout.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendLayout.tsx new file mode 100644 index 00000000000..f28ab03baac --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendLayout.tsx @@ -0,0 +1,57 @@ +import { ChartLabel, ChartLegend, ChartDonut, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + x: string; + y: number; +} + +export const ChartLegendLayout: React.FunctionComponent = () => { + // Custom legend label component + const LegendLabel = ({ values, ...rest }) => ( + + ); + + // Custom legend component + const getLegend = (legendData, values) => ( + } + rowGutter={20} + /> + ); + + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendComponent={getLegend([{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }], [35, 55, 10])} + legendOrientation="vertical" + legendPosition="right" + name="chart9" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + title="100" + themeColor={ChartThemeColor.multiOrdered} + width={375} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendLinks.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendLinks.tsx new file mode 100644 index 00000000000..0a544be49b5 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendLinks.tsx @@ -0,0 +1,116 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLabel, + ChartLegend, + ChartLine, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number; + symbol?: { type: string }; +} + +export const ChartLegendLinks: React.FunctionComponent = () => { + // Custom legend label component + const LegendLabel = ({ _datum, ...rest }) => ( + + + + ); + + // Custom legend component + const getLegend = (legendData) => } />; + + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} + constrainToVisibleArea + /> + } + legendComponent={getLegend([{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }])} + legendData={legendData} + legendPosition="bottom" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart8" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + width={450} + > + } /> + } + /> + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendResponsiveBottomLeft.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendResponsiveBottomLeft.tsx new file mode 100644 index 00000000000..5b2e8151d44 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendResponsiveBottomLeft.tsx @@ -0,0 +1,83 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useRef, useState, useEffect } from 'react'; + +interface Data { + name?: string; + y?: number; +} + +export const ChartLegendResponsiveBottomLeft: React.FunctionComponent = () => { + const containerRef = useRef(null); + const [extraHeight, setExtraHeight] = useState(0); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + const handleLegendAllowWrap = (newExtraHeight: number) => { + if (newExtraHeight !== extraHeight) { + setExtraHeight(newExtraHeight); + } + }; + + const getHeight = (baseHeight: number) => baseHeight + extraHeight; + + useEffect(() => { + const observer = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer(); + }; + }, []); + + const comparativeWarningMeasureData: Data[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: Data[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: Data[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]; + const primarySegmentedMeasureLegendData: Data[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: Data[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: Data[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + const height = getHeight(200); + + return ( +
    + `${datum.name}: ${datum.y}`} + legendAllowWrap={handleLegendAllowWrap} + legendPosition="bottom-left" + maxDomain={{ y: 100 }} + name="chart3" + padding={{ + bottom: 50, + left: 50, + right: 50, + top: 100 // Adjusted to accommodate labels + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + titlePosition="top-left" + width={width} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendStandalone.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendStandalone.tsx new file mode 100644 index 00000000000..374fa17c231 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendStandalone.tsx @@ -0,0 +1,90 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLegend, + ChartLine, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number; + symbol?: { type: string }; +} + +export const ChartLegendStandalone: React.FunctionComponent = () => { + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + const data5: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart4" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.green} + width={450} + > + + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendTooltips.tsx b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendTooltips.tsx new file mode 100644 index 00000000000..1069dabe637 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegend/examples/ChartLegendTooltips.tsx @@ -0,0 +1,55 @@ +import { ChartLabel, ChartLegend, ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { Tooltip } from '@patternfly/react-core'; +import { useRef } from 'react'; + +interface PetData { + x: string; + y: number; +} + +export const ChartLegendTooltips: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + // Custom legend label component + // Note: Tooltip wraps children with a div tag, so we use a reference to ChartLabel instead + const LegendLabel = ({ datum, ...rest }) => { + const ref = useRef(null); + return ( + + + + + ); + }; + + // Custom legend component + const getLegend = (legendData) => } />; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendComponent={getLegend([{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }])} + legendPosition="bottom" + name="chart7" + padding={{ + bottom: 65, + left: 20, + right: 20, + top: 20 + }} + themeColor={ChartThemeColor.multiOrdered} + width={300} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltip.test.tsx b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltip.test.tsx new file mode 100644 index 00000000000..02671cfcf0d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltip.test.tsx @@ -0,0 +1,101 @@ +import { render } from '@testing-library/react'; +import { Chart } from '../Chart/Chart'; +import { ChartAxis } from '../ChartAxis/ChartAxis'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartLine } from '../ChartLine/ChartLine'; +import { ChartThemeColor } from '../ChartTheme/ChartThemeColor'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartLegend } from '../ChartLegend/ChartLegend'; +import { createContainer } from '../ChartUtils/chart-container'; +import { ChartLegendTooltip } from './ChartLegendTooltip'; + +Object.values([true, false]).forEach(() => { + test('ChartLegendTooltip', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('allows tooltip via container component', () => { + const CursorVoronoiContainer = createContainer('cursor', 'voronoi'); + const legendData = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + const { asFragment } = render( + `${datum.y !== null ? datum.y : 'no data'}`} + labelComponent={ + datum.x} /> + } + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom" + legendComponent={} />} + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.green} + width={450} + > + } /> + } /> + + + + + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.tsx b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltip.tsx similarity index 88% rename from packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.tsx rename to packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltip.tsx index a2d5a7b70dc..7588e9cc5a0 100644 --- a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.tsx +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltip.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { Helpers, @@ -9,26 +9,26 @@ import { VictoryStyleObject } from 'victory-core'; import { VictoryTooltip } from 'victory-tooltip'; -import { ChartCursorTooltip, ChartCursorTooltipProps } from '../ChartCursorTooltip'; +import { ChartCursorTooltip, ChartCursorTooltipProps } from '../ChartCursorTooltip/ChartCursorTooltip'; import { ChartLegendTooltipContent } from './ChartLegendTooltipContent'; -import { ChartLegendTooltipStyles, ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; +import { ChartLegendTooltipStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; import { getLegendTooltipDataProps, getLegendTooltipSize, getLegendTooltipVisibleData, - getLegendTooltipVisibleText, - getTheme -} from '../ChartUtils'; + getLegendTooltipVisibleText +} from '../ChartUtils/chart-tooltip'; +import { getTheme } from '../ChartUtils/chart-theme'; /** * The ChartLegendTooltip is based on ChartCursorTooltip, which is intended to be used with a voronoi cursor * container. This works best with charts such as area and line, for example. * - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-tooltip/src/index.d.ts + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-tooltip/src/index.d.ts */ -export interface ChartLegendTooltipProps extends ChartCursorTooltipProps { +export interface ChartLegendTooltipProps extends Omit { /** * The active prop specifies whether the tooltip component should be displayed. */ @@ -42,13 +42,14 @@ export interface ChartLegendTooltipProps extends ChartCursorTooltipProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ activePoints?: any[]; /** * The angle prop specifies the angle to rotate the tooltip around its origin point. */ - angle?: string | number; + angle?: number; /** * The center prop determines the position of the center of the tooltip flyout. This prop should be given as an object * that describes the desired x and y svg coordinates of the center of the tooltip. This prop is useful for @@ -159,6 +160,7 @@ export interface ChartLegendTooltipProps extends ChartCursorTooltipProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ height?: number; @@ -225,6 +227,16 @@ export interface ChartLegendTooltipProps extends ChartCursorTooltipProps { * @propType string | Function */ orientation?: OrientationOrCallback; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; /** * The pointerLength prop determines the length of the triangular pointer extending from the flyout. This prop may be * given as a positive number or a function of datum. @@ -263,11 +275,13 @@ export interface ChartLegendTooltipProps extends ChartCursorTooltipProps { * * @propType number | string | Function | string[] | number[] */ - text?: StringOrNumberOrCallback | string[] | number[]; + text?: string[] | StringOrNumberOrCallback; /** * The theme prop specifies a theme to use for determining styles and layout properties for a component. Any styles or * props defined in theme may be overwritten by props specified on the component instance. * + * Note: Theme may be overridden when flyout is rendered + * * @propType object */ theme?: ChartThemeDefinition; @@ -279,21 +293,13 @@ export interface ChartLegendTooltipProps extends ChartCursorTooltipProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title prop specifies a title to render with the legend. - * This prop should be given as a string, or an array of strings for multi-line titles. * - * Example: title={(datum) => datum.x} + * @propType number | string | Function | string[] + * @example title={(datum) => datum.x} */ - title?: string | string[] | Function; + title?: string[] | StringOrNumberOrCallback; /** * This prop refers to the width of the svg that ChartLegendTooltip is rendered within. This prop is passed from * parents of ChartLegendTooltip, and should not be set manually. In versions before ^33.0.0 this prop referred to the @@ -301,6 +307,7 @@ export interface ChartLegendTooltipProps extends ChartCursorTooltipProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ width?: number; @@ -321,28 +328,30 @@ interface FlyoutProps { export const ChartLegendTooltip: React.FunctionComponent = ({ activePoints, - datum, center = { x: 0, y: 0 }, + datum, flyoutHeight, flyoutWidth, height, isCursorTooltip = true, labelComponent = , legendData, + patternScale, text, themeColor, - themeVariant, title, width, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartLegendTooltipProps) => { - const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength) : 10; + const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength, undefined) : 10; const legendTooltipProps = () => ({ legendData: getLegendTooltipVisibleData({ activePoints, legendData, text, theme }), - legendProps: getLegendTooltipDataProps(labelComponent.props.legendComponent), + legendProps: getLegendTooltipDataProps( + labelComponent.props.legendComponent ? labelComponent.props.legendComponent.props : undefined + ), text: getLegendTooltipVisibleText({ activePoints, legendData, text }), theme }); @@ -358,12 +367,13 @@ export const ChartLegendTooltip: React.FunctionComponent - React.cloneElement(labelComponent, { + cloneElement(labelComponent, { center, flyoutHeight: flyoutHeight || getFlyoutHeight(props), flyoutWidth: flyoutWidth || getFlyoutWidth(props), height, legendData, + patternScale, title, width, ...labelComponent.props @@ -378,7 +388,7 @@ export const ChartLegendTooltip: React.FunctionComponent : ; - return React.cloneElement(tooltipComponent, { + return cloneElement(tooltipComponent, { activePoints, center, datum, @@ -391,6 +401,7 @@ export const ChartLegendTooltip: React.FunctionComponent { + test('ChartLegendTooltipContent', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component text', () => { + const legendData = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipContent.tsx b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipContent.tsx similarity index 83% rename from packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipContent.tsx rename to packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipContent.tsx index f59879b4076..87231098f77 100644 --- a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipContent.tsx +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipContent.tsx @@ -1,22 +1,24 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { Helpers, NumberOrCallback, StringOrNumberOrCallback } from 'victory-core'; import { VictoryLegend } from 'victory-legend'; -import { ChartLabel } from '../ChartLabel'; -import { ChartLegend } from '../ChartLegend'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartLegend } from '../ChartLegend/ChartLegend'; +import { ChartLegendTooltipStyles } from '../ChartTheme/ChartStyles'; import { ChartLegendTooltipLabel } from './ChartLegendTooltipLabel'; -import { ChartLegendTooltipStyles, ChartThemeDefinition } from '../ChartTheme'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; import { getLegendTooltipDataProps, getLegendTooltipSize, getLegendTooltipVisibleData, - getLegendTooltipVisibleText, - getTheme -} from '../ChartUtils'; + getLegendTooltipVisibleText +} from '../ChartUtils/chart-tooltip'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-legend/src/index.d.ts + * ChartLegendTooltipContent renders a legend tooltip component. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-legend/src/index.d.ts */ export interface ChartLegendTooltipContentProps { /** @@ -24,6 +26,7 @@ export interface ChartLegendTooltipContentProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ activePoints?: any[]; @@ -39,7 +42,7 @@ export interface ChartLegendTooltipContentProps { * Victory components can pass a datum prop to their label component. This can be used to calculate functional styles, * and determine child text */ - datum?: {}; + datum?: any; /** * The dx prop defines a horizontal shift from the x coordinate. * @@ -116,6 +119,16 @@ export interface ChartLegendTooltipContentProps { type?: string; }; }[]; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; /** * The text prop defines the text ChartTooltip will render. The text prop may be given as a string, number, or * function of datum. When ChartLabel is used as the labelComponent, strings may include newline characters, which @@ -142,14 +155,6 @@ export interface ChartLegendTooltipContentProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The title prop specifies a title to render with the legend. * This prop should be given as a string, or an array of strings for multi-line titles. @@ -192,18 +197,18 @@ export const ChartLegendTooltipContent: React.FunctionComponent, legendComponent = , legendData, + patternScale, text, themeColor, - themeVariant, title, titleComponent = , width, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartLegendTooltipContentProps) => { - const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength) : 10; + const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength, undefined) : 10; const legendProps = getLegendTooltipDataProps(legendComponent.props); const visibleLegendData = getLegendTooltipVisibleData({ activePoints, @@ -225,7 +230,7 @@ export const ChartLegendTooltipContent: React.FunctionComponent center.x + _flyoutWidth + pointerLength) { return center.x + ChartLegendTooltipStyles.flyout.padding / 2; } else if (center.x < _flyoutWidth + pointerLength) { @@ -241,7 +246,7 @@ export const ChartLegendTooltipContent: React.FunctionComponent height - _flyoutHeight / 2) { @@ -261,12 +266,14 @@ export const ChartLegendTooltipContent: React.FunctionComponent - React.cloneElement(labelComponent, { + cloneElement(labelComponent, { + datum, dx: maxLegendDimensions.width - minLegendDimensions.width, legendData: visibleLegendData, ...labelComponent.props @@ -276,43 +283,46 @@ export const ChartLegendTooltipContent: React.FunctionComponent { const _title = title instanceof Function ? title(datum) : title; - return React.cloneElement(titleComponent, { + return cloneElement(titleComponent, { style: { fill: ChartLegendTooltipStyles.label.fill, fontWeight: ChartLegendTooltipStyles.label.fontWeight }, text: _title, textAnchor: 'start', - x: getX() + titleOffsetX + Helpers.evaluateProp(dx), - y: getY() + titleOffsetY + Helpers.evaluateProp(dy), + x: getX() + titleOffsetX + Helpers.evaluateProp(dx, undefined), + y: getY() + titleOffsetY + Helpers.evaluateProp(dy, undefined), ...titleComponent.props }); }; - // Returns the legebd component + // Returns the legend component const getLegendComponent = () => - React.cloneElement(legendComponent, { + cloneElement(legendComponent, { data: getLegendTooltipVisibleData({ activePoints, colorScale: legendProps.colorScale, legendData, + patternScale, text, textAsLegendData: true, theme }), labelComponent: getLabelComponent(), + patternScale, standalone: false, theme, - x: getX() + legendOffsetX + Helpers.evaluateProp(dx), - y: getY() + legendOffsetY + Helpers.evaluateProp(dy), + themeColor, + x: getX() + legendOffsetX + Helpers.evaluateProp(dx, undefined), + y: getY() + legendOffsetY + Helpers.evaluateProp(dy, undefined), ...legendProps }); return ( - + {getTitleComponent()} {getLegendComponent()} - + ); }; ChartLegendTooltipContent.displayName = 'ChartLegendTooltipContent'; diff --git a/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipLabel.test.tsx b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipLabel.test.tsx new file mode 100644 index 00000000000..6b6733b9b4e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipLabel.test.tsx @@ -0,0 +1,28 @@ +import { render } from '@testing-library/react'; +import { ChartLegendTooltipLabel } from './ChartLegendTooltipLabel'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; + +Object.values([true, false]).forEach(() => { + test('ChartLegendTooltipLabel', () => { + const { asFragment } = render(} />); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component text', () => { + const legendData = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + const { asFragment } = render( + } + valueLabelComponent={} + /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipLabel.tsx b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipLabel.tsx similarity index 85% rename from packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipLabel.tsx rename to packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipLabel.tsx index 3069ef17be1..0e9a2a1beb1 100644 --- a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltipLabel.tsx +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/ChartLegendTooltipLabel.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement, Fragment } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import defaults from 'lodash/defaults'; import { @@ -11,13 +11,15 @@ import { VictoryLabel, VictoryLabelProps } from 'victory-core'; -import { ChartLabel } from '../ChartLabel'; -import { ChartLegendTooltipStyles } from '../ChartTheme'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartLegendTooltipStyles } from '../ChartTheme/ChartStyles'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts + * ChartLegendLabel renders a legend tooltip label + * + * See https://github.com/FormidableLabs/victory/tree/main/packages/victory-core/src/victory-label */ -export interface ChartLegendLabelProps extends VictoryLabelProps { +export interface ChartLegendTooltipLabelProps extends VictoryLabelProps { /** * The active prop specifies whether the label is active or not. The active prop is set by defaultEvents in components * like ChartTooltip and VictorySelectionContainer. The active prop is used when evaluating functional styles and @@ -44,6 +46,8 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { * Note: This prop should not be set manually. * * @propType number | string | Function + * + * @private Not intended as public API and subject to change * @hide */ children?: StringOrNumberOrCallback; @@ -52,7 +56,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { */ className?: string; /** - * Labels that apply to an entire data series will recieve the entire series as `data` instead of an individual datum + * Labels that apply to an entire data series will receive the entire series as `data` instead of an individual datum * prop. */ data?: any[]; @@ -60,7 +64,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { * Victory components can pass a datum prop to their label component. This can be used to calculate functional styles, * and determine child text */ - datum?: {}; + datum?: any; /** * The desc prop specifies the description of the chart/SVG to assist with accessibility for screen readers. The more * descriptive this title is, the more useful it will be for people using screen readers. @@ -93,6 +97,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ index?: string | number; @@ -104,7 +109,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { /** * The labelPlacement prop is used to specify the placement of labels relative to the data point they represent. * This prop may be given as “vertical”, “parallel” or “perpendicular”. This props is particularly useful in polar - * charts, where it may be desireable to position a label either parallel or perpendicular to its corresponding angle. + * charts, where it may be desirable to position a label either parallel or perpendicular to its corresponding angle. * When this prop is not set, perpendicular label placement will be used for polar charts, and vertical label * placement will be used for cartesian charts. * @@ -126,7 +131,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { }; }[]; /** - * The valueLabelComponent prop takes a component instance which will be used to render each legend tooltip. + * The legendLabelComponent prop takes a component instance which will be used to render each legend tooltip. */ legendLabelComponent?: React.ReactElement; /** @@ -152,6 +157,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -166,6 +172,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ scale?: { x?: any; y?: any }; @@ -194,6 +201,10 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { * In addition to being a string, it can be an object containing transform definitions for easier authoring. */ transform?: string | {} | (() => string | {}); + /** + * The valueLabelComponent prop takes a component instance which will be used to render each legend tooltip. + */ + valueLabelComponent?: React.ReactElement; /** * The verticalAnchor prop defines how the text is vertically positioned relative to the given `x` and `y` * coordinates. Options are "start", "middle" and "end". @@ -207,6 +218,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ width?: number; @@ -220,7 +232,7 @@ export interface ChartLegendLabelProps extends VictoryLabelProps { y?: number; } -export const ChartLegendTooltipLabel: React.FunctionComponent = ({ +export const ChartLegendTooltipLabel: React.FunctionComponent = ({ dx = 0, index = 0, legendData, @@ -228,12 +240,13 @@ export const ChartLegendTooltipLabel: React.FunctionComponent, x, y, // destructure last ...rest -}: ChartLegendLabelProps) => { +}: ChartLegendTooltipLabelProps) => { const getStyle = (styles: any) => { const applyDefaultStyle = (customStyle: React.CSSProperties) => defaults( @@ -250,7 +263,7 @@ export const ChartLegendTooltipLabel: React.FunctionComponent { const label = legendData && legendData.length ? legendData[index as any].name : undefined; - return React.cloneElement(legendLabelComponent, { + return cloneElement(legendLabelComponent, { style: getStyle({}), text: label, textAnchor: 'start', @@ -260,17 +273,25 @@ export const ChartLegendTooltipLabel: React.FunctionComponent { - const _x = x + Helpers.evaluateProp(dx); - return ; + const _x = x + (Helpers.evaluateProp(dx, undefined) as number); + + return cloneElement(valueLabelComponent, { + style: getStyle(style), + text, + textAnchor, + x: _x, + y, + ...rest + }); }; const legendLabel = getLegendLabelComponent(); const valueLabel = getValueLabelComponent(); return ( - + {legendLabel} {valueLabel} - + ); }; ChartLegendTooltipLabel.displayName = 'ChartLegendTooltipLabel'; diff --git a/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltip.test.tsx.snap b/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltip.test.tsx.snap new file mode 100644 index 00000000000..3c0560cd3a5 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltip.test.tsx.snap @@ -0,0 +1,542 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartLegendTooltip 1`] = ``; + +exports[`ChartLegendTooltip 2`] = ``; + +exports[`allows tooltip via container component 1`] = ` + +
    + + + Average number of pets + + + + + + + + 2015 + + + + + + + + 2016 + + + + + + + + 2017 + + + + + + + + 2018 + + + + + + + + + + + + 2 + + + + + + + + + 5 + + + + + + + + + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cats + + + + + Dogs + + + + + Birds + + + + + Mice + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipContent.test.tsx.snap b/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipContent.test.tsx.snap new file mode 100644 index 00000000000..9f9db62b2bc --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipContent.test.tsx.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartLegendTooltipContent 1`] = ` + + + + + +`; + +exports[`ChartLegendTooltipContent 2`] = ` + + + + + +`; + +exports[`renders component text 1`] = ` + + + + + +`; diff --git a/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipLabel.test.tsx.snap b/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipLabel.test.tsx.snap new file mode 100644 index 00000000000..b6832ff72af --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLegendTooltip/__snapshots__/ChartLegendTooltipLabel.test.tsx.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartLegendTooltipLabel 1`] = ``; + +exports[`ChartLegendTooltipLabel 2`] = ``; + +exports[`renders component text 1`] = ` + + + + Cats + + + + + 1, 2, 3, 4 + + + +`; diff --git a/packages/react-charts/src/components/ChartLine/ChartLine.test.tsx b/packages/react-charts/src/victory/components/ChartLine/ChartLine.test.tsx similarity index 75% rename from packages/react-charts/src/components/ChartLine/ChartLine.test.tsx rename to packages/react-charts/src/victory/components/ChartLine/ChartLine.test.tsx index f1027786bd8..aabebe15844 100644 --- a/packages/react-charts/src/components/ChartLine/ChartLine.test.tsx +++ b/packages/react-charts/src/victory/components/ChartLine/ChartLine.test.tsx @@ -1,18 +1,17 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Chart } from '../Chart'; -import { ChartGroup } from '../ChartGroup'; +import { render } from '@testing-library/react'; +import { Chart } from '../Chart/Chart'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; import { ChartLine } from './ChartLine'; Object.values([true, false]).forEach(() => { test('ChartLine', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); }); test('renders component data', () => { - const view = shallow( + const { asFragment } = render( { ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-charts/src/components/ChartLine/ChartLine.tsx b/packages/react-charts/src/victory/components/ChartLine/ChartLine.tsx similarity index 93% rename from packages/react-charts/src/components/ChartLine/ChartLine.tsx rename to packages/react-charts/src/victory/components/ChartLine/ChartLine.tsx index 06508e83dbe..10cf5ed78c0 100644 --- a/packages/react-charts/src/components/ChartLine/ChartLine.tsx +++ b/packages/react-charts/src/victory/components/ChartLine/ChartLine.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -20,18 +20,17 @@ import { VictoryStyleInterface } from 'victory-core'; import { VictoryLine, VictoryLineProps, VictoryLineTTargetType } from 'victory-line'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getTheme } from '../ChartUtils'; - -export enum ChartLineSortOrder { - ascending = 'ascending', - descending = 'descending' -} +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-line/src/index.d.ts + * ChartLine renders a dataset as a single line path. Since ChartLine renders only a single element to represent a + * dataset rather than individual elements for each data point, some of its behavior is different from other Victory + * based components. Pay special attention to style and events props, and take advantage of ChartVoronoiContainer to + * enable tooltips. ChartLine can be composed with Chart to create line charts. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-line/src/victory-line.tsx */ export interface ChartLineProps extends VictoryLineProps { /** @@ -129,7 +128,7 @@ export interface ChartLineProps extends VictoryLineProps { * Since ChartLine only renders a single element, the eventKey property is not used. * The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -221,7 +220,7 @@ export interface ChartLineProps extends VictoryLineProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -236,7 +235,7 @@ export interface ChartLineProps extends VictoryLineProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -272,6 +271,7 @@ export interface ChartLineProps extends VictoryLineProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -315,6 +315,7 @@ export interface ChartLineProps extends VictoryLineProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -326,7 +327,7 @@ export interface ChartLineProps extends VictoryLineProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -341,7 +342,7 @@ export interface ChartLineProps extends VictoryLineProps { * is given directly to the lodash sortBy function to be executed on the * final dataset. */ - sortKey?: string | string[] | Function; + sortKey?: DataGetterPropType; /** * The sortOrder prop specifies whether sorted data should be returned in 'ascending' or 'descending' order. * @@ -382,14 +383,6 @@ export interface ChartLineProps extends VictoryLineProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -435,14 +428,13 @@ export interface ChartLineProps extends VictoryLineProps { export const ChartLine: React.FunctionComponent = ({ containerComponent = , themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartLineProps) => { // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { theme, ...containerComponent.props }); diff --git a/packages/react-charts/src/victory/components/ChartLine/__snapshots__/ChartLine.test.tsx.snap b/packages/react-charts/src/victory/components/ChartLine/__snapshots__/ChartLine.test.tsx.snap new file mode 100644 index 00000000000..9cd8d583862 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLine/__snapshots__/ChartLine.test.tsx.snap @@ -0,0 +1,600 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartLine 1`] = ` + +
    + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartLine 2`] = ` + +
    + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + + + + + + + + 1.5 + + + + + + + + 2.0 + + + + + + + + 2.5 + + + + + + + + 3.0 + + + + + + + + 3.5 + + + + + + + + 4.0 + + + + + + + + + + + 2 + + + + + + + + 4 + + + + + + + + 6 + + + + + + + + 8 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartLine/examples/ChartLine.md b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLine.md new file mode 100644 index 00000000000..312ff2e3cb9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLine.md @@ -0,0 +1,64 @@ +--- +id: Line chart +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartAxis', + 'ChartGroup', + 'ChartLine', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { useEffect, useRef, useState } from 'react'; +import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor, ChartLegendTooltip, ChartVoronoiContainer, createContainer } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { VictoryZoomContainer } from 'victory-zoom-container'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic with right aligned legend +```ts file = "ChartLineBasicRightLegend.tsx" + +``` + +### Green with bottom aligned legend + +This demonstrates how to combine cursor and voronoi containers to display tooltips along with a cursor. + +```ts file = "ChartLineGreenBottomLegend.tsx" + +``` + +### Multi-color (unordered) with responsive container + +This demonstrates zoom for the x axis only. + +```ts file = "ChartLineMultiColor.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` +- The `theme` and `themeColor` props should be applied at the most top level component +- Use `ChartGroup` to apply theme color scales and other properties to multiple components + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartLine` props, see [Victoryline](https://formidable.com/open-source/victory/docs/victory-line) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) +- For `VictoryZoomContainer` props, see [VictoryZoomContainerline](https://formidable.com/open-source/victory/docs/victory-zoom-container) diff --git a/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineBasicRightLegend.tsx b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineBasicRightLegend.tsx new file mode 100644 index 00000000000..e90bceb462a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineBasicRightLegend.tsx @@ -0,0 +1,83 @@ +import { Chart, ChartAxis, ChartGroup, ChartLine, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number; + symbol?: { type: string }; +} + +export const ChartLineBasicRightLegend: React.FunctionComponent = () => { + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart1" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + width={600} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineGreenBottomLegend.tsx b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineGreenBottomLegend.tsx new file mode 100644 index 00000000000..3be1539ec5e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineGreenBottomLegend.tsx @@ -0,0 +1,102 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLine, + ChartThemeColor, + ChartLegendTooltip, + createContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; + childName?: string; + symbol?: { type: string }; +} + +export const ChartLineGreenBottomLegend: React.FunctionComponent = () => { + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData: PetData[] = [ + { childName: 'cats', name: 'Cats' }, + { childName: 'dogs', name: 'Dogs', symbol: { type: 'dash' } }, + { childName: 'birds', name: 'Birds' }, + { childName: 'mice', name: 'Mice' } + ]; + const data1: PetData[] = [ + { x: '2015', y: 1 }, + { x: '2016', y: 2 }, + { x: '2017', y: 5 }, + { x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { x: '2015', y: 2 }, + { x: '2016', y: 1 }, + { x: '2017', y: 7 }, + { x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { x: '2015', y: 3 }, + { x: '2016', y: 4 }, + { x: '2017', y: 9 }, + { x: '2018', y: 5 } + ]; + const data4: PetData[] = [ + { x: '2015', y: 3 }, + { x: '2016', y: 3 }, + { x: '2017', y: 8 }, + { x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.y}`} + labelComponent={ datum.x} />} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart2" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.green} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineMultiColor.tsx b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineMultiColor.tsx new file mode 100644 index 00000000000..03d44fa757c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartLine/examples/ChartLineMultiColor.tsx @@ -0,0 +1,103 @@ +import { Chart, ChartAxis, ChartGroup, ChartLine, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; +import { VictoryZoomContainer } from 'victory-zoom-container'; + +interface PetData { + x?: string; + y?: number; + name?: string; + symbol?: { type: string }; +} + +export const ChartLineMultiColor: React.FunctionComponent = () => { + const containerRef = useRef(null); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + useEffect(() => { + const observer = getResizeObserver(containerRef.current, handleResize); + handleResize(); + return () => { + observer(); + }; + }, []); + + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    +
    + } + legendData={legendData} + legendPosition="bottom-left" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart3" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + + + + + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartPie/ChartPie.test.tsx b/packages/react-charts/src/victory/components/ChartPie/ChartPie.test.tsx new file mode 100644 index 00000000000..0a56a343fb7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPie/ChartPie.test.tsx @@ -0,0 +1,24 @@ +import { render } from '@testing-library/react'; +import { ChartPie } from './ChartPie'; + +Object.values([true, false]).forEach(() => { + test('ChartPie', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/victory/components/ChartPie/ChartPie.tsx b/packages/react-charts/src/victory/components/ChartPie/ChartPie.tsx new file mode 100644 index 00000000000..45b47fef7a3 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPie/ChartPie.tsx @@ -0,0 +1,678 @@ +import { cloneElement, Fragment, useEffect } from 'react'; +import hoistNonReactStatics from 'hoist-non-react-statics'; +import { + AnimatePropTypeInterface, + CategoryPropType, + DataGetterPropType, + EventCallbackInterface, + EventPropTypeInterface, + Helpers, + NumberOrCallback, + OriginType, + PaddingProps, + SliceNumberOrCallback, + SortOrderPropType, + StringOrNumberOrCallback, + StringOrNumberOrList, + VictoryStyleInterface +} from 'victory-core'; +import { + SliceProps, + VictoryPie, + VictoryPieProps, + VictorySliceLabelPositionType, + VictorySliceTTargetType +} from 'victory-pie'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartLegend } from '../ChartLegend/ChartLegend'; +import { ChartCommonStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; +import { getComputedLegend, getLegendItemsExtraHeight, getLegendMaxTextWidth } from '../ChartUtils/chart-legend'; +import { getPaddingForSide } from '../ChartUtils/chart-padding'; +import { getPatternDefs, useDefaultPatternProps } from '../ChartUtils/chart-patterns'; +import { getTheme } from '../ChartUtils/chart-theme'; +import { ChartPoint } from '../ChartPoint/ChartPoint'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; + +/** + * ChartPie renders a dataset as a pie chart. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-pie/src/index.d.ts + */ +export interface ChartPieProps extends VictoryPieProps { + /** + * Specifies the tooltip capability of the container component. A value of true allows the chart to add a + * ChartTooltip component to the labelComponent property. This is a shortcut to display tooltips when the labels + * property is also provided. + */ + allowTooltip?: boolean; + /** + * The animate prop specifies props for VictoryAnimation to use. + * The animate prop should also be used to specify enter and exit + * transition configurations with the `onExit` and `onEnter` namespaces respectively. + * + * @propType boolean | object + * @example + * {duration: 500, onExit: () => {}, onEnter: {duration: 500, before: () => ({y: 0})})} + */ + animate?: boolean | AnimatePropTypeInterface; + /** + * The ariaDesc prop specifies the description of the chart/SVG to assist with + * accessibility for screen readers. + * + * Note: Overridden by the desc prop of containerComponent + */ + ariaDesc?: string; + /** + * The ariaTitle prop specifies the title to be applied to the SVG to assist + * accessibility for screen readers. + * + * Note: Overridden by the title prop of containerComponent + */ + ariaTitle?: string; + /** + * The categories prop specifies how categorical data for a chart should be ordered. + * This prop should be given as an array of string values, or an object with + * these arrays of values specified for x and y. If this prop is not set, + * categorical data will be plotted in the order it was given in the data array + * + * @propType string[] | { x: string[], y: string[] } + * @example ["dogs", "cats", "mice"] + */ + categories?: CategoryPropType; + /** + * The colorScale prop is an optional prop that defines the color scale the pie + * will be created on. This prop should be given as an array of CSS colors, or as a string + * corresponding to one of the built in color scales. ChartPie will automatically assign + * values from this color scale to the pie slices unless colors are explicitly provided in the + * data object + */ + colorScale?: string[]; + /** + * The constrainToVisibleArea prop determines whether to coerce tooltips so that they fit within the visible area of + * the chart. When this prop is set to true, tooltip pointers will still point to the correct data point, but the + * center of the tooltip will be shifted to fit within the overall width and height of the svg Victory renders. + */ + constrainToVisibleArea?: boolean; + /** + * The containerComponent prop takes an entire component which will be used to + * create a container element for standalone charts. + * The new element created from the passed containerComponent wil be provided with + * these props from ChartPie: height, width, children + * (the chart itself) and style. Props that are not provided by the + * child chart component include title and desc, both of which + * are intended to add accessibility to Victory components. The more descriptive these props + * are, the more accessible your data will be for people using screen readers. + * Any of these props may be overridden by passing in props to the supplied component, + * or modified or ignored within the custom component itself. If a dataComponent is + * not provided, ChartPie will use the default ChartContainer component. + * + * @example + */ + containerComponent?: React.ReactElement; + /** + * Set the cornerRadius for every dataComponent (Slice by default) within ChartPie + * + * @propType number | Function + */ + cornerRadius?: SliceNumberOrCallback; + /** + * The data prop specifies the data to be plotted, + * where data X-value is the slice label (string or number), + * and Y-value is the corresponding number value represented by the slice + * Data should be in the form of an array of data points. + * Each data point may be any format you wish (depending on the `x` and `y` accessor props), + * but by default, an object with x and y properties is expected. + * + * @example [{x: 1, y: 2}, {x: 2, y: 3}], [[1, 2], [2, 3]], + * [[{x: "a", y: 1}, {x: "b", y: 2}], [{x: "a", y: 2}, {x: "b", y: 3}]] + */ + data?: any[]; + /** + * The dataComponent prop takes an entire, HTML-complete data component which will be used to + * create slices for each datum in the pie chart. The new element created from the passed + * dataComponent will have the property datum set by the pie chart for the point it renders; + * properties style and pathFunction calculated by ChartPie; an index property set + * corresponding to the location of the datum in the data provided to the pie; events bound to + * the ChartPie; and the d3 compatible slice object. + * If a dataComponent is not provided, ChartPie's Slice component will be used. + */ + dataComponent?: React.ReactElement; + /** + * The overall end angle of the pie in degrees. This prop is used in conjunction with + * startAngle to create a pie that spans only a segment of a circle. + */ + endAngle?: number; + /** + * Similar to data accessor props `x` and `y`, this prop may be used to functionally + * assign eventKeys to data + * + * @propType number | string | Function + */ + eventKey?: StringOrNumberOrCallback; + /** + * The event prop takes an array of event objects. Event objects are composed of + * a target, an eventKey, and eventHandlers. Targets may be any valid style namespace + * for a given component, so "data" and "labels" are all valid targets for ChartPie + * events. The eventKey may optionally be used to select a single element by index rather than + * an entire set. The eventHandlers object should be given as an object whose keys are standard + * event names (i.e. onClick) and whose values are event callbacks. The return value + * of an event handler is used to modify elements. The return value should be given + * as an object or an array of objects with optional target and eventKey keys, + * and a mutation key whose value is a function. The target and eventKey keys + * will default to those corresponding to the element the event handler was attached to. + * The mutation function will be called with the calculated props for the individual selected + * element (i.e. a single bar), and the object returned from the mutation function + * will override the props of the selected element via object assignment. + * + * @propType object[] + * @example + * events={[ + * { + * target: "data", + * eventKey: 1, + * eventHandlers: { + * onClick: () => { + * return [ + * { + * eventKey: 2, + * mutation: (props) => { + * return {style: merge({}, props.style, {fill: "orange"})}; + * } + * }, { + * eventKey: 2, + * target: "labels", + * mutation: () => { + * return {text: "hey"}; + * } + * } + * ]; + * } + * } + * } + * ]} + */ + events?: EventPropTypeInterface[]; + /** + * ChartPie uses the standard externalEventMutations prop. + * + * @propType object[] + */ + externalEventMutations?: EventCallbackInterface[]; + /** + * The groupComponent prop takes an entire component which will be used to + * create group elements for use within container elements. This prop defaults + * to a tag on web, and a react-native-svg tag on mobile + */ + groupComponent?: React.ReactElement; + /** + * The hasPatterns prop is an optional prop that indicates whether a pattern is shown for a chart. + * SVG patterns are dynamically generated (unique to each chart) in order to apply colors from the selected + * color theme or custom color scale. Those generated patterns are applied in a specific order (via a URL), similar + * to the color theme ordering defined by PatternFly. If the multi-color theme was in use; for example, colorized + * patterns would be displayed in that same order. Create custom patterns via the patternScale prop. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example hasPatterns={ true } + * @example hasPatterns={[ true, true, false ]} + */ + hasPatterns?: boolean | boolean[]; + /** + * Specifies the height the svg viewBox of the chart container. This value should be given as a + * number of pixels. + * + * Because Victory renders responsive containers, the width and height props do not determine the width and + * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of + * pixels will depend on the size of the container the chart is rendered into. + * + * Note: When adding a legend, height (the overall SVG height) may need to be larger than pieHeight (the pie size) + * in order to accommodate the extra legend. + * + * By default, pieHeight is the min. of either height or width. This covers most use cases in order to accommodate + * legends within the same SVG. However, pieHeight (not height) may need to be set in order to adjust the pie height. + * + * Typically, the parent container is set to the same width in order to maintain the aspect ratio. + */ + height?: number; + /** + * When creating a donut chart, this prop determines the number of pixels between + * the center of the chart and the inner edge. When this prop is set to zero + * a regular pie chart is rendered. + * + * @propType number | Function + */ + innerRadius?: NumberOrCallback; + /** + * The labelComponent prop takes in an entire label component which will be used + * to create a label for the area. The new element created from the passed labelComponent + * will be supplied with the following properties: x, y, index, data, verticalAnchor, + * textAnchor, angle, style, text, and events. any of these props may be overridden + * by passing in props to the supplied component, or modified or ignored within + * the custom component itself. If labelComponent is omitted, a new ChartLabel + * will be created with props described above. This labelComponent prop should be used to + * provide a series label for ChartPie. If individual labels are required for each + * data point, they should be created by composing ChartPie with VictoryScatter + */ + labelComponent?: React.ReactElement; + /** + * The labelPosition prop specifies the angular position of each label relative to its corresponding slice. + * This prop should be given as "startAngle", "endAngle", "centroid", or as a function that returns one of these + * values. When this prop is not given, the label will be positioned at the centroid of each slice. + * + * @propType string | Function + */ + labelPosition?: VictorySliceLabelPositionType | ((props: SliceProps) => VictorySliceLabelPositionType); + /** + * The labelRadius prop defines the radius of the arc that will be used for positioning each slice label. + * If this prop is not set, the label radius will default to the radius of the pie + label padding. + * + * @propType number | Function + */ + labelRadius?: number | ((props: SliceProps) => number); + /** + * The labels prop defines labels that will appear above each bar in your chart. + * This prop should be given as an array of values or as a function of data. + * If given as an array, the number of elements in the array should be equal to + * the length of the data array. Labels may also be added directly to the data object + * like data={[{x: 1, y: 1, label: "first"}]}. + * + * @example ["spring", "summer", "fall", "winter"], (datum) => datum.title + */ + labels?: string[] | number[] | ((data: any) => string | number | null); + /** + * Allows legend items to wrap onto the next line if the chart is not wide enough. + * + * Note that the chart's SVG height and width are 100% by default, so it can be responsive itself. However, if you + * define the height and width of the chart's parent container, you must accommodate for extra legend height due to + * legend items wrapping onto the next line. When the height of the chart's parent container is too small, some legend + * items may not be visible. + * + * Alternatively, a callback function may be provided, which will be called after the legend's itemsPerRow property + * has been calculated. The value provided can be used to increase the chart's parent container height as legend + * items wrap onto the next line. If no adjustment is necessary, the value will be zero. + * + * Note: This is overridden by the legendItemsPerRow property + */ + legendAllowWrap?: boolean | ((extraHeight: number) => void); + /** + * The legend component to render with chart. + * + * Note: Use legendData so the legend width can be calculated and positioned properly. + * Default legend properties may be applied + */ + legendComponent?: React.ReactElement; + /** + * Specify data via the data prop. ChartLegend expects data as an + * array of objects with name (required), symbol, and labels properties. + * The data prop must be given as an array. + * + * @example legendData={[{ name: `GBps capacity - 45%` }, { name: 'Unused' }]} + */ + legendData?: { + name?: string; + symbol?: { + fill?: string; + type?: string; + }; + }[]; + /** + * The orientation prop takes a string that defines whether legend data + * are displayed in a row or column. When orientation is "horizontal", + * legend items will be displayed in a single row. When orientation is + * "vertical", legend items will be displayed in a single column. Line + * and text-wrapping is not currently supported, so "vertical" + * orientation is both the default setting and recommended for + * displaying many series of data. + */ + legendOrientation?: 'horizontal' | 'vertical'; + /** + * The legend position relation to the pie chart. Valid values are 'bottom' and 'right' + * + * Note: When adding a legend, padding may need to be adjusted in order to accommodate the extra legend. In some + * cases, the legend may not be visible until enough padding is applied. + */ + legendPosition?: 'bottom' | 'right'; + /** + * Text direction of the legend labels. + */ + legendDirection?: 'ltr' | 'rtl'; + /** + * The name prop is typically used to reference a component instance when defining shared events. However, this + * optional prop may also be applied to child elements as an ID prefix. This is a workaround to ensure Victory + * based components output unique IDs when multiple charts appear in a page. + */ + name?: string; + /** + * Victory components will pass an origin prop is to define the center point in svg coordinates for polar charts. + * + * Note: It will not typically be necessary to set an origin prop manually + * + * @propType { x: number, y: number } + */ + origin?: OriginType; + /** + * The padAngle prop determines the amount of separation between adjacent data slices + * in number of degrees + * + * @propType number | Function + */ + padAngle?: NumberOrCallback; + /** + * The padding props specifies the amount of padding in number of pixels between + * the edge of the chart and any rendered child components. This prop can be given + * as a number or as an object with padding specified for top, bottom, left + * and right. + * + * @propType number | { top: number, bottom: number, left: number, right: number } + */ + padding?: PaddingProps; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; + /** + * Moves the given pattern index to top of scale, used to sync patterns with ChartDonutThreshold + * + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + patternUnshiftIndex?: number; + /** + * Specifies the radius of the chart. If this property is not provided it is computed + * from width, height, and padding props + * + * @propType number | Function + */ + radius?: NumberOrCallback; + /** + * The sharedEvents prop is used internally to coordinate events between components. + * + * Note: This prop should not be set manually. + * + * @private Not intended as public API and subject to change + * @hide + */ + sharedEvents?: { events: any[]; getEventState: Function }; + /** + * Use the sortKey prop to indicate how data should be sorted. This prop + * is given directly to the lodash sortBy function to be executed on the final dataset. + * + * @propType number | string | Function | string[] + */ + sortKey?: DataGetterPropType; + /** + * The sortOrder prop specifies whether sorted data should be returned in 'ascending' or 'descending' order. + * + * @propType string + */ + sortOrder?: SortOrderPropType; + /** + * The standalone prop determines whether the component will render a standalone svg + * or a tag that will be included in an external svg. Set standalone to false to + * compose ChartPie with other components within an enclosing tag. + */ + standalone?: boolean; + /** + * The overall start angle of the pie in degrees. This prop is used in conjunction with + * endAngle to create a pie that spans only a segment of a circle. + */ + startAngle?: number; + /** + * The style prop specifies styles for your pie. ChartPie relies on Radium, + * so valid Radium style objects should work for this prop. Height, width, and + * padding should be specified via the height, width, and padding props. + * + * @propType { parent: object, data: object, labels: object } + * @example {data: {stroke: "black"}, label: {fontSize: 10}} + */ + style?: VictoryStyleInterface; + /** + * The theme prop takes a style object with nested data, labels, and parent objects. + * You can create this object yourself, or you can use a theme provided by + * When using ChartPie as a solo component, implement the theme directly on + * ChartPie. If you are wrapping ChartPie in ChartChart or ChartGroup, + * please call the theme on the outermost wrapper component instead. + * + * @propType object + */ + theme?: ChartThemeDefinition; + /** + * Specifies the theme color. Valid values are 'blue', 'green', 'multi', etc. + * + * Note: Not compatible with theme prop + * + * @example themeColor={ChartThemeColor.blue} + */ + themeColor?: string; + /** + * Specifies the width of the svg viewBox of the chart container. This value should be given as a number of pixels. + * + * Because Victory renders responsive containers, the width and height props do not determine the width and + * height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number of + * pixels will depend on the size of the container the chart is rendered into. Typically, the parent container is set + * to the same width in order to maintain the aspect ratio. + */ + width?: number; + /** + * The x prop specifies how to access the X value of each data point. + * If given as a function, it will be run on each data point, and returned value will be used. + * If given as an integer, it will be used as an array index for array-type data points. + * If given as a string, it will be used as a property key for object-type data points. + * If given as an array of strings, or a string containing dots or brackets, + * it will be used as a nested object property path (for details see Lodash docs for _.get). + * If `null` or `undefined`, the data value will be used as is (identity function/pass-through). + * + * @propType number | string | Function | string[] + * @example 0, 'x', 'x.value.nested.1.thing', 'x[2].also.nested', null, d => Math.sin(d) + */ + x?: DataGetterPropType; + /** + * The y prop specifies how to access the Y value of each data point. + * If given as a function, it will be run on each data point, and returned value will be used. + * If given as an integer, it will be used as an array index for array-type data points. + * If given as a string, it will be used as a property key for object-type data points. + * If given as an array of strings, or a string containing dots or brackets, + * it will be used as a nested object property path (for details see Lodash docs for _.get). + * If `null` or `undefined`, the data value will be used as is (identity function/pass-through). + * + * @propType number | string | Function | string[] + * @example 0, 'y', 'y.value.nested.1.thing', 'y[2].also.nested', null, d => Math.sin(d) + */ + y?: DataGetterPropType; +} + +export const ChartPie: React.FunctionComponent = ({ + allowTooltip = true, + ariaDesc, + ariaTitle, + colorScale, + constrainToVisibleArea = false, + containerComponent = , + hasPatterns, + legendAllowWrap = false, + legendComponent = , + legendData, + legendPosition = ChartCommonStyles.legend.position, + legendDirection = 'ltr', + name, + patternScale, + patternUnshiftIndex, + padding, + radius, + standalone = true, + style, + themeColor, + // destructure last + theme = getTheme(themeColor), + labelComponent = allowTooltip ? ( + + ) : undefined, + legendOrientation = theme.legend.orientation as any, + height = theme.pie.height, + width = theme.pie.width, + ...rest +}: ChartPieProps) => { + const defaultPadding = { + bottom: getPaddingForSide('bottom', padding, theme.pie.padding), + left: getPaddingForSide('left', padding, theme.pie.padding), + right: getPaddingForSide('right', padding, theme.pie.padding), + top: getPaddingForSide('top', padding, theme.pie.padding) + }; + + const { defaultColorScale, defaultPatternScale, isPatternDefs, patternId } = useDefaultPatternProps({ + colorScale, + hasPatterns, + patternScale, + themeColorScale: theme.pie.colorScale as string[] + }); + + // Ensure non-negative value is returned + const getDefaultRadius = () => { + const result = Helpers.getRadius({ + height, + width, + padding: defaultPadding + }); + return result > -1 ? result : undefined; + }; + const chartRadius = radius ? radius : getDefaultRadius(); + + // Merge pattern IDs with `style.data.fill` property + const getDefaultStyle = () => { + if (!defaultPatternScale) { + return style; + } + const _style = style ? { ...style } : {}; + _style.data = { + fill: ({ slice }: any) => { + const pattern = defaultPatternScale[slice.index % defaultPatternScale.length]; + return pattern ? pattern : defaultColorScale[slice.index % defaultColorScale.length]; + }, + ..._style.data + }; + return _style; + }; + + const chart = ( + + ); + + let legendXOffset = 0; + if (legendDirection === 'rtl') { + legendXOffset = getLegendMaxTextWidth(legendData, theme); + } + + const legend = cloneElement(legendComponent, { + colorScale, + data: legendData, + ...(name && { name: `${name}-${(legendComponent as any).type.displayName}` }), + key: 'pf-chart-pie-legend', + orientation: legendOrientation, + theme, + themeColor, + ...(legendDirection === 'rtl' && { + dataComponent: legendComponent.props.dataComponent ? ( + cloneElement(legendComponent.props.dataComponent, { transform: `translate(${legendXOffset})` }) + ) : ( + + ) + }), + ...(legendDirection === 'rtl' && { + labelComponent: legendComponent.props.labelComponent ? ( + cloneElement(legendComponent.props.labelComponent, { direction: 'rtl', dx: legendXOffset - 30 }) + ) : ( + + ) + }), + ...legendComponent.props + }); + + // Returns a computed legend + const getLegend = () => { + if (!legend.props.data) { + return null; + } + return getComputedLegend({ + allowWrap: legendAllowWrap === true || typeof legendAllowWrap === 'function', + chartType: 'pie', + height, + legendComponent: legend, + padding: defaultPadding, + position: legendPosition, + theme, + width, + ...(defaultPatternScale && { patternScale: defaultPatternScale }) + }); + }; + + // Clone so users can override container props + const container = standalone + ? cloneElement( + containerComponent, + { + desc: ariaDesc, + height, + title: ariaTitle, + width, + theme, + ...containerComponent.props + }, + [ + chart, + getLegend(), + isPatternDefs && getPatternDefs({ patternId, colorScale: defaultColorScale, patternUnshiftIndex }) + ] + ) + : null; + + // Callback to compliment legendAllowWrap + const computedLegend = getLegend(); + useEffect(() => { + if (computedLegend?.props && typeof legendAllowWrap === 'function') { + const extraHeight = getLegendItemsExtraHeight({ + legendData: computedLegend.props.data, + legendOrientation: computedLegend.props.orientation, + legendProps: computedLegend.props, + theme + }); + legendAllowWrap(extraHeight); + } + }, [computedLegend, legendAllowWrap, theme, width]); + + return standalone ? ( + {container} + ) : ( + + {chart} + {computedLegend} + {isPatternDefs && getPatternDefs({ patternId, colorScale: defaultColorScale, patternUnshiftIndex })} + + ); +}; +ChartPie.displayName = 'ChartPie'; + +// Note: VictoryPie.role must be hoisted +hoistNonReactStatics(ChartPie, VictoryPie); diff --git a/packages/react-charts/src/victory/components/ChartPie/__snapshots__/ChartPie.test.tsx.snap b/packages/react-charts/src/victory/components/ChartPie/__snapshots__/ChartPie.test.tsx.snap new file mode 100644 index 00000000000..7a4c38a61d8 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPie/__snapshots__/ChartPie.test.tsx.snap @@ -0,0 +1,182 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartPie 1`] = ` + +
    + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartPie 2`] = ` + +
    + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartPie/examples/ChartPie.md b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPie.md new file mode 100644 index 00000000000..2c6fb564b1d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPie.md @@ -0,0 +1,48 @@ +--- +id: Pie chart +section: components +subsection: charts +propComponents: ['ChartPie'] +hideDarkMode: true +--- + +import { ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; +import chart_theme_blue_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_100'; +import chart_theme_yellow_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_100'; +import chart_theme_orange_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_300'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic with right aligned legend +```ts file = "ChartPieBasicRightLegend.tsx" + +``` + +### Multi-color (ordered) with bottom aligned legend +```ts file = "ChartPieMultiColorBottomLegend.tsx" + +``` + +### Custom color scale + +This demonstrates how to apply a custom color scale. + +```ts file = "ChartPieCustomColorScale.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `ChartPie` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) diff --git a/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieBasicRightLegend.tsx b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieBasicRightLegend.tsx new file mode 100644 index 00000000000..293f88205fd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieBasicRightLegend.tsx @@ -0,0 +1,40 @@ +import { ChartPie } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartPieBasicRightLegend: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart1" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieCustomColorScale.tsx b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieCustomColorScale.tsx new file mode 100644 index 00000000000..b531671f617 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieCustomColorScale.tsx @@ -0,0 +1,51 @@ +import { ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; +import chart_theme_blue_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_100'; +import chart_theme_yellow_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_100'; +import chart_theme_orange_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_300'; + +interface Data { + x?: string; + y?: number; + name?: string; +} + +export const ChartPieCustomColorScale: React.FunctionComponent = () => { + const data: Data[] = [ + { x: 'Sky', y: 38 }, + { x: 'Shady side of pyramid', y: 7 }, + { x: 'Sunny side of pyramid', y: 17 }, + { x: 'Sky', y: 38 } + ]; + const legendData: Data[] = [{ name: 'Sky' }, { name: 'Shady side of pyramid' }, { name: 'Sunny side of pyramid' }]; + + return ( +
    + `${datum.x}`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart2" + padding={{ + bottom: 20, + left: 20, + right: 240, // Adjusted to accommodate legend + top: 20 + }} + themeColor={ChartThemeColor.orange} + width={450} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieMultiColorBottomLegend.tsx b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieMultiColorBottomLegend.tsx new file mode 100644 index 00000000000..670c01ac2a7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPie/examples/ChartPieMultiColorBottomLegend.tsx @@ -0,0 +1,40 @@ +import { ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartPieMultiColorBottomLegend: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendPosition="bottom" + name="chart3" + padding={{ + bottom: 65, + left: 20, + right: 20, + top: 20 + }} + themeColor={ChartThemeColor.multiOrdered} + width={300} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartPoint/ChartPoint.test.tsx b/packages/react-charts/src/victory/components/ChartPoint/ChartPoint.test.tsx new file mode 100644 index 00000000000..a478e918757 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPoint/ChartPoint.test.tsx @@ -0,0 +1,31 @@ +import { render } from '@testing-library/react'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartLegend } from '../ChartLegend/ChartLegend'; +import { ChartPoint } from './ChartPoint'; + +Object.values([true, false]).forEach(() => { + test('ChartPoint', () => { + const { asFragment } = render( + } + labelComponent={} + titleComponent={} + /> + ); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const { asFragment } = render( + } + labelComponent={} + /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartPoint/ChartPoint.tsx b/packages/react-charts/src/victory/components/ChartPoint/ChartPoint.tsx similarity index 96% rename from packages/react-charts/src/components/ChartPoint/ChartPoint.tsx rename to packages/react-charts/src/victory/components/ChartPoint/ChartPoint.tsx index 14f6010b8c3..5bbe892c1cb 100644 --- a/packages/react-charts/src/components/ChartPoint/ChartPoint.tsx +++ b/packages/react-charts/src/victory/components/ChartPoint/ChartPoint.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import { Helpers, Path } from 'victory-core'; import { PathHelpers, PathHelpersInterface } from './path-helpers'; @@ -133,7 +133,7 @@ const getPath = (props: ChartPointProps) => { threshold: PathHelpers.threshold }; const symbol = Helpers.evaluateProp(props.symbol, props); - const key: keyof PathHelpersInterface = symbol; + const key = symbol as keyof PathHelpersInterface; const symbolFunction = typeof pathFunctions[key] === 'function' ? pathFunctions[key] : pathFunctions.square; return symbolFunction(x, y, size); }; @@ -166,7 +166,7 @@ export const ChartPoint: React.FunctionComponent = ({ ...rest }; - return React.cloneElement(pathComponent, { + return cloneElement(pathComponent, { className, clipPath, d: getPath(props), diff --git a/packages/react-charts/src/victory/components/ChartPoint/__snapshots__/ChartPoint.test.tsx.snap b/packages/react-charts/src/victory/components/ChartPoint/__snapshots__/ChartPoint.test.tsx.snap new file mode 100644 index 00000000000..3ea24a0e4ed --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartPoint/__snapshots__/ChartPoint.test.tsx.snap @@ -0,0 +1,304 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartPoint 1`] = ` + +
    + + + + + + + Series 1 + + + + + Series 2 + + + +
    + +
    +
    +
    +`; + +exports[`ChartPoint 2`] = ` + +
    + + + + + + + Series 1 + + + + + Series 2 + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + Average number of pets + + + + + Cats + + + + + Dogs + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/components/ChartPoint/assets/Eyecon.svg b/packages/react-charts/src/victory/components/ChartPoint/assets/Eyecon.svg similarity index 100% rename from packages/react-charts/src/components/ChartPoint/assets/Eyecon.svg rename to packages/react-charts/src/victory/components/ChartPoint/assets/Eyecon.svg diff --git a/packages/react-charts/src/components/ChartPoint/path-helpers.ts b/packages/react-charts/src/victory/components/ChartPoint/path-helpers.ts similarity index 98% rename from packages/react-charts/src/components/ChartPoint/path-helpers.ts rename to packages/react-charts/src/victory/components/ChartPoint/path-helpers.ts index f1a3aec6fac..d2f6fb0d727 100644 --- a/packages/react-charts/src/components/ChartPoint/path-helpers.ts +++ b/packages/react-charts/src/victory/components/ChartPoint/path-helpers.ts @@ -104,7 +104,7 @@ export const PathHelpers: PathHelpersInterface = { star: (x: number, y: number, size: number) => { const baseSize = 1.35 * size; const angle = Math.PI / 5; - const starCoords = [...Array(10).keys()].map(index => { + const starCoords = [...Array(10).keys()].map((index) => { const length = index % 2 === 0 ? baseSize : baseSize / 2; return `${length * Math.sin(angle * (index + 1)) + x}, ${length * Math.cos(angle * (index + 1)) + y}`; diff --git a/packages/react-charts/src/components/ChartScatter/ChartScatter.test.tsx b/packages/react-charts/src/victory/components/ChartScatter/ChartScatter.test.tsx similarity index 83% rename from packages/react-charts/src/components/ChartScatter/ChartScatter.test.tsx rename to packages/react-charts/src/victory/components/ChartScatter/ChartScatter.test.tsx index 7130bc08c71..765735b6623 100644 --- a/packages/react-charts/src/components/ChartScatter/ChartScatter.test.tsx +++ b/packages/react-charts/src/victory/components/ChartScatter/ChartScatter.test.tsx @@ -1,18 +1,17 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { Chart } from '../Chart/Chart'; import { ChartGroup } from '../ChartGroup/ChartGroup'; import { ChartScatter } from './ChartScatter'; Object.values([true, false]).forEach(() => { test('ChartScatter', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); }); test('renders component data', () => { - const view = shallow( + const { asFragment } = render( { ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-charts/src/components/ChartScatter/ChartScatter.tsx b/packages/react-charts/src/victory/components/ChartScatter/ChartScatter.tsx similarity index 93% rename from packages/react-charts/src/components/ChartScatter/ChartScatter.tsx rename to packages/react-charts/src/victory/components/ChartScatter/ChartScatter.tsx index d5827b32c58..60256cdef8c 100644 --- a/packages/react-charts/src/components/ChartScatter/ChartScatter.tsx +++ b/packages/react-charts/src/victory/components/ChartScatter/ChartScatter.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -20,18 +20,15 @@ import { VictoryStyleInterface } from 'victory-core'; import { VictoryScatter, VictoryScatterProps, VictoryScatterTTargetType } from 'victory-scatter'; -import { ChartContainer } from '../ChartContainer'; -import { ChartScatterStyles, ChartThemeDefinition } from '../ChartTheme'; -import { getTheme } from '../ChartUtils'; - -export enum ChartScatterSortOrder { - ascending = 'ascending', - descending = 'descending' -} +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartScatterStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-scatter/src/index.d.ts + * ChartScatter renders a dataset as a series of points. ChartScatter can be composed with Chart to create scatter plots. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-scatter/src/index.d.ts */ export interface ChartScatterProps extends VictoryScatterProps { /** @@ -134,7 +131,7 @@ export interface ChartScatterProps extends VictoryScatterProps { * Since ChartScatter only renders a single element, the eventKey property is not used. * The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -221,7 +218,7 @@ export interface ChartScatterProps extends VictoryScatterProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -240,7 +237,7 @@ export interface ChartScatterProps extends VictoryScatterProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -276,6 +273,7 @@ export interface ChartScatterProps extends VictoryScatterProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -319,6 +317,7 @@ export interface ChartScatterProps extends VictoryScatterProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -330,7 +329,7 @@ export interface ChartScatterProps extends VictoryScatterProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -399,14 +398,6 @@ export interface ChartScatterProps extends VictoryScatterProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -452,21 +443,25 @@ export interface ChartScatterProps extends VictoryScatterProps { export const ChartScatter: React.FunctionComponent = ({ containerComponent = , themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), - size = ({ active }) => (active ? ChartScatterStyles.activeSize : ChartScatterStyles.size), + theme = getTheme(themeColor), ...rest }: ChartScatterProps) => { // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { theme, ...containerComponent.props }); + // bubbleProperty is only considered if the size prop is undefined, therefore set + // default size function only if bubbleProperty is not set. + if (typeof rest.size === 'undefined' && typeof rest.bubbleProperty === 'undefined') { + rest.size = ({ active }) => (active ? ChartScatterStyles.activeSize : ChartScatterStyles.size); + } + // Note: containerComponent is required for theme - return ; + return ; }; ChartScatter.displayName = 'ChartScatter'; diff --git a/packages/react-charts/src/victory/components/ChartScatter/__snapshots__/ChartScatter.test.tsx.snap b/packages/react-charts/src/victory/components/ChartScatter/__snapshots__/ChartScatter.test.tsx.snap new file mode 100644 index 00000000000..c7d7fcc364c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartScatter/__snapshots__/ChartScatter.test.tsx.snap @@ -0,0 +1,1623 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartScatter 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartScatter 2`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + + + + + + + + 2.0 + + + + + + + + 3.0 + + + + + + + + 4.0 + + + + + + + + 5.0 + + + + + + + + 6.0 + + + + + + + + 7.0 + + + + + + + + + + + 1.0 + + + + + + + + 2.0 + + + + + + + + 3.0 + + + + + + + + 4.0 + + + + + + + + 5.0 + + + + + + + + 6.0 + + + + + + + + 7.0 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatter.md b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatter.md new file mode 100644 index 00000000000..47322e03200 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatter.md @@ -0,0 +1,71 @@ +--- +id: Scatter chart +section: components +subsection: charts +propComponents: [ +'Chart', +'ChartArea', +'ChartAxis', +'ChartGroup', +'ChartLine', +'ChartScatter', +'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { +Chart, +ChartArea, +ChartAxis, +ChartGroup, +ChartLine, +ChartScatter, +ChartThemeColor, +ChartVoronoiContainer, +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic +```ts file = "ChartScatterBasic.tsx" + +``` + +### Line chart + +This demonstrates how to add interactive data points to a line chart. + +```ts file = "ChartScatterLineChart.tsx" + +``` + +### Area chart + +This demonstrates how to add interactive data points to an area chart. + +```ts file = "ChartScatterAreaChart.tsx" + +``` + +## Documentation + +- For single data points or zero values, you may want to set the `domain` prop. See Victory's FAQ + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartLine` props, see [VictoryLine](https://formidable.com/open-source/victory/docs/victory-line) +- For `ChartScatter` props, see [VictoryScatter](https://formidable.com/open-source/victory/docs/victory-scatter) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterAreaChart.tsx b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterAreaChart.tsx new file mode 100644 index 00000000000..d9c6dc41713 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterAreaChart.tsx @@ -0,0 +1,107 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartScatter, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useState, useRef, useEffect } from 'react'; + +export const ChartScatterAreaChart: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + const series = [ + { + datapoints: [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ], + legendItem: { name: 'Cats' } + }, + { + datapoints: [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 3 }, + { name: 'Dogs', x: '2017', y: 4 }, + { name: 'Dogs', x: '2018', y: 5 }, + { name: 'Dogs', x: '2019', y: 6 } + ], + legendItem: { name: 'Dogs' } + }, + { + datapoints: [ + { name: 'Birds', x: '2015', y: 1 }, + { name: 'Birds', x: '2016', y: 2 }, + { name: 'Birds', x: '2017', y: 3 }, + { name: 'Birds', x: '2018', y: 2 }, + { name: 'Birds', x: '2019', y: 4 } + ], + legendItem: { name: 'Birds' } + } + ]; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + return ( +
    +
    + (datum.childName.includes('area-') ? `${datum.name}: ${datum.y}` : null)} + constrainToVisibleArea + /> + } + height={225} + legendData={series.map((s) => s.legendItem)} + legendPosition="bottom-left" + name="chart3" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + {series.map((s, idx) => ( + + ))} + + + {series.map((s, idx) => ( + + ))} + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterBasic.tsx b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterBasic.tsx new file mode 100644 index 00000000000..abaec09b802 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterBasic.tsx @@ -0,0 +1,39 @@ +import { Chart, ChartAxis, ChartGroup, ChartScatter, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartScatterBasic: React.FunctionComponent = () => { + const data: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 4 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + height={275} + maxDomain={{ y: 8 }} + minDomain={{ y: 0 }} + name="chart1" + width={450} + > + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterLineChart.tsx b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterLineChart.tsx new file mode 100644 index 00000000000..7466aa240d8 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartScatter/examples/ChartScatterLineChart.tsx @@ -0,0 +1,119 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLine, + ChartScatter, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +export const ChartScatterLineChart: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + const series = [ + { + datapoints: [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ], + legendItem: { name: 'Cats' } + }, + { + datapoints: [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ], + legendItem: { name: 'Dogs' }, + style: { + data: { + strokeDasharray: '3,3' + } + } + }, + { + datapoints: [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ], + legendItem: { name: 'Birds' } + }, + { + datapoints: [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ], + legendItem: { name: 'Mice' } + } + ]; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + return ( +
    +
    + (datum.childName.includes('line-') ? `${datum.name}: ${datum.y}` : null)} + constrainToVisibleArea + /> + } + legendData={series.map((s) => s.legendItem)} + legendPosition="bottom-left" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart2" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.orange} + width={width} + > + + + + {series.map((s, idx) => ( + + ))} + + + {series.map((s, idx) => ( + + ))} + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/components/ChartStack/ChartStack.test.tsx b/packages/react-charts/src/victory/components/ChartStack/ChartStack.test.tsx similarity index 77% rename from packages/react-charts/src/components/ChartStack/ChartStack.test.tsx rename to packages/react-charts/src/victory/components/ChartStack/ChartStack.test.tsx index f2555690ce1..0b36c2836f1 100644 --- a/packages/react-charts/src/components/ChartStack/ChartStack.test.tsx +++ b/packages/react-charts/src/victory/components/ChartStack/ChartStack.test.tsx @@ -1,18 +1,17 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Chart } from '../Chart'; -import { ChartBar } from '../ChartBar'; +import { render } from '@testing-library/react'; +import { Chart } from '../Chart/Chart'; +import { ChartBar } from '../ChartBar/ChartBar'; import { ChartStack } from './ChartStack'; Object.values([true, false]).forEach(() => { test('ChartStack', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); }); test('renders component data', () => { - const view = shallow( + const { asFragment } = render( { ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-charts/src/components/ChartStack/ChartStack.tsx b/packages/react-charts/src/victory/components/ChartStack/ChartStack.tsx similarity index 84% rename from packages/react-charts/src/components/ChartStack/ChartStack.tsx rename to packages/react-charts/src/victory/components/ChartStack/ChartStack.tsx index 6a297dce271..51074b31ba8 100644 --- a/packages/react-charts/src/components/ChartStack/ChartStack.tsx +++ b/packages/react-charts/src/victory/components/ChartStack/ChartStack.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { AnimatePropTypeInterface, @@ -17,13 +17,18 @@ import { VictoryStyleInterface } from 'victory-core'; import { VictoryStack, VictoryStackProps, VictoryStackTTargetType } from 'victory-stack'; -import { ChartContainer } from '../ChartContainer'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getClassName, getTheme } from '../ChartUtils'; +import { ChartContainer } from '../ChartContainer/ChartContainer'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getClassName } from '../ChartUtils/chart-helpers'; +import { useDefaultPatternProps, renderChildrenWithPatterns } from '../ChartUtils/chart-patterns'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-stack/src/index.d.ts + * ChartStack is a wrapper component that renders a given set of children in a stacked layout. Like other wrapper + * components, ChartStack also reconciles the domain and layout for all its children, and coordinates animations and + * shared events. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-stack/src/index.d.ts */ export interface ChartStackProps extends VictoryStackProps { /** @@ -56,7 +61,7 @@ export interface ChartStackProps extends VictoryStackProps { * these values for x and y. When categories are not given as an object * When this prop is set on a wrapper component, it will dictate the categories of * its the children. If this prop is not set, any categories on child component - * or catigorical data, will be merged to create a shared set of categories. + * or categorical data, will be merged to create a shared set of categories. * * @propType string[] | { x: string[], y: string[] } * @example ["dogs", "cats", "mice"] @@ -133,7 +138,7 @@ export interface ChartStackProps extends VictoryStackProps { * may optionally be used to select a single element by index or eventKey rather than * an entire set. The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey and childName keys, * and a mutation key whose value is a function. The target and eventKey and childName keys * will default to those corresponding to the element the event handler was attached to. @@ -181,6 +186,19 @@ export interface ChartStackProps extends VictoryStackProps { * to a tag on web, and a react-native-svg tag on mobile */ groupComponent?: React.ReactElement; + /** + * The hasPatterns prop is an optional prop that indicates whether a pattern is shown for a chart. + * SVG patterns are dynamically generated (unique to each chart) in order to apply colors from the selected + * color theme or custom color scale. Those generated patterns are applied in a specific order (via a URL), similar + * to the color theme ordering defined by PatternFly. If the multi-color theme was in use; for example, colorized + * patterns would be displayed in that same order. Create custom patterns via the patternScale prop. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example hasPatterns={ true } + * @example hasPatterns={[ true, true, false ]} + */ + hasPatterns?: boolean | boolean[]; /** * The height props specifies the height the svg viewBox of the chart container. * This value should be given as a number of pixels @@ -219,7 +237,7 @@ export interface ChartStackProps extends VictoryStackProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -234,7 +252,7 @@ export interface ChartStackProps extends VictoryStackProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -265,11 +283,22 @@ export interface ChartStackProps extends VictoryStackProps { * @propType number | { top: number, bottom: number, left: number, right: number } */ padding?: PaddingProps; + /** + * The patternScale prop is an optional prop that defines patterns to apply, where applicable. This prop should be + * given as a string array of pattern URLs. Patterns will be assigned to children by index and will repeat when there + * are more children than patterns in the provided patternScale. Use null to omit the pattern for a given index. + * + * Note: Not all components are supported; for example, ChartLine, ChartBullet, ChartThreshold, etc. + * + * @example patternScale={[ 'url("#pattern1")', 'url("#pattern2")', null ]} + */ + patternScale?: string[]; /** * Victory components can pass a boolean polar prop to specify whether a label is part of a polar chart. * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -308,6 +337,7 @@ export interface ChartStackProps extends VictoryStackProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -319,7 +349,7 @@ export interface ChartStackProps extends VictoryStackProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -360,14 +390,6 @@ export interface ChartStackProps extends VictoryStackProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -384,16 +406,18 @@ export const ChartStack: React.FunctionComponent = ({ ariaDesc, ariaTitle, children, + colorScale, containerComponent = , + hasPatterns, + patternScale, themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartStackProps) => { // Clone so users can override container props - const container = React.cloneElement(containerComponent, { + const container = cloneElement(containerComponent, { desc: ariaDesc, title: ariaTitle, theme, @@ -401,10 +425,20 @@ export const ChartStack: React.FunctionComponent = ({ className: getClassName({ className: containerComponent.props.className }) // Override VictoryContainer class name }); + const { defaultPatternScale } = useDefaultPatternProps({ + colorScale, + hasPatterns, + patternScale, + themeColorScale: theme.stack.colorScale as string[] + }); + // Note: containerComponent is required for theme return ( - - {children} + + {renderChildrenWithPatterns({ + children, + patternScale: defaultPatternScale + })} ); }; diff --git a/packages/react-charts/src/victory/components/ChartStack/__snapshots__/ChartStack.test.tsx.snap b/packages/react-charts/src/victory/components/ChartStack/__snapshots__/ChartStack.test.tsx.snap new file mode 100644 index 00000000000..c0e8fdf17f6 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/__snapshots__/ChartStack.test.tsx.snap @@ -0,0 +1,648 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartStack 1`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`ChartStack 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cats + + + + + + + + Dogs + + + + + + + + Birds + + + + + + + + Mice + + + + + + + + + + + 5 + + + + + + + + 10 + + + + + + + + 15 + + + + + + + + 20 + + + + + + + + 25 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStack.md b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStack.md new file mode 100644 index 00000000000..10874b7b437 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStack.md @@ -0,0 +1,84 @@ +--- +id: Stack chart +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartArea', + 'ChartBar', + 'ChartStack', + 'ChartTooltip' +] +hideDarkMode: true +--- + +import { + Chart, + ChartArea, + ChartAxis, + ChartBar, + ChartStack, + ChartLegendTooltip, + ChartThemeColor, + ChartTooltip, + ChartVoronoiContainer, + createContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic with right aligned legend +```ts file = "ChartStackBasicRightLegend.tsx" + +``` + +### Horizontal with bottom aligned legend +```ts file = "ChartStackBottomLegend.tsx" + +``` + +### Multi-color (ordered) horizontal with bottom aligned legend + +This demonstrates an alternate way of applying tooltips using data labels. + +```ts file = "ChartStackMultiColorOrdered.tsx" + +``` + +### Monthly data with responsive container +```ts file = "ChartStackMonthlyResponsive.tsx" + +``` + +### Multi-color (unordered) responsive container + +This demonstrates monthly data with a bottom aligned legend and responsiveness for mobile. + +```ts file = "ChartStackMultiColorUnordered.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` +- Themes are inherited, so a default theme may override `themeColor` for a child component +- The `theme` and `themeColor` props should be applied at the most top level component + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartStack` props, see [VictoryStack](https://formidable.com/open-source/victory/docs/victory-stack) +- For `ChartTooltip` props, see [VictoryTooltip](https://formidable.com/open-source/victory/docs/victory-tooltip) diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBasicRightLegend.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBasicRightLegend.tsx new file mode 100644 index 00000000000..a135dff5b0d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBasicRightLegend.tsx @@ -0,0 +1,68 @@ +import { Chart, ChartAxis, ChartBar, ChartStack, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartStackBasicRightLegend: React.FunctionComponent = () => { + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domainPadding={{ x: [30, 25] }} + legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} + legendOrientation="vertical" + legendPosition="right" + height={250} + name="chart1" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + width={600} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBottomLegend.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBottomLegend.tsx new file mode 100644 index 00000000000..3f5906a1a5c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBottomLegend.tsx @@ -0,0 +1,75 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartStack, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartStackBottomLegend: React.FunctionComponent = () => { + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domainPadding={{ x: [30, 25] }} + legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]} + legendPosition="bottom" + height={275} + name="chart2" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.yellow} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMonthlyResponsive.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMonthlyResponsive.tsx new file mode 100644 index 00000000000..2cd320a132d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMonthlyResponsive.tsx @@ -0,0 +1,107 @@ +import { Chart, ChartAxis, ChartBar, ChartStack, ChartTooltip } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +interface Bar { + x: string; + y: number; +} + +export const ChartStackMonthlyResponsive: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + const bars: Bar[] = []; + for (let i = 1; i < 32; i++) { + bars.push({ x: `Aug. ${i}`, y: Math.floor(Math.random() * 6) + 1 }); + } + + const renderSocketBars = () => { + const socketBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Sockets', + label: `${tick.x} Sockets: ${tick.y}` + })); + return } />; + }; + + const renderCoresBars = () => { + const coresBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Cores', + label: `${tick.x} Cores: ${tick.y}` + })); + return } />; + }; + + const renderNodesBars = () => { + const nodesBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Nodes', + label: `${tick.x} Nodes: ${tick.y}` + })); + return } />; + }; + + const getTickValues = (offset = 2) => { + const tickValues = []; + for (let i = 1; i < 32; i++) { + if (i % offset === 0) { + tickValues.push(`Aug. ${i}`); + } + } + return tickValues; + }; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + return ( +
    +
    + + + + + {renderSocketBars()} + {renderCoresBars()} + {renderNodesBars()} + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorOrdered.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorOrdered.tsx new file mode 100644 index 00000000000..39eb4222bfb --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorOrdered.tsx @@ -0,0 +1,74 @@ +import { + Chart, + ChartBar, + ChartAxis, + ChartStack, + ChartThemeColor, + ChartTooltip +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number; + label?: string; +} + +export const ChartStackMultiColorOrdered: React.FunctionComponent = () => { + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1, label: 'Cats: 1' }, + { name: 'Cats', x: '2016', y: 2, label: 'Cats: 2' }, + { name: 'Cats', x: '2017', y: 5, label: 'Cats: 5' }, + { name: 'Cats', x: '2018', y: 3, label: 'Cats: 3' } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2, label: 'Dogs: 2' }, + { name: 'Dogs', x: '2016', y: 1, label: 'Dogs: 1' }, + { name: 'Dogs', x: '2017', y: 7, label: 'Dogs: 7' }, + { name: 'Dogs', x: '2018', y: 4, label: 'Dogs: 4' } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4, label: 'Birds: 4' }, + { name: 'Birds', x: '2016', y: 4, label: 'Birds: 4' }, + { name: 'Birds', x: '2017', y: 9, label: 'Birds: 9' }, + { name: 'Birds', x: '2018', y: 7, label: 'Birds: 7' } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3, label: 'Mice: 3' }, + { name: 'Mice', x: '2016', y: 3, label: 'Mice: 3' }, + { name: 'Mice', x: '2017', y: 8, label: 'Mice: 8' }, + { name: 'Mice', x: '2018', y: 5, label: 'Mice: 5' } + ]; + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + + return ( +
    + + + + + } /> + } /> + } /> + } /> + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorUnordered.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorUnordered.tsx new file mode 100644 index 00000000000..a714e23bde2 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorUnordered.tsx @@ -0,0 +1,114 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartStack, + ChartLegendTooltip, + ChartThemeColor, + createContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +interface Data { + x: string; + y: number; +} + +export const ChartStackMultiColorUnordered: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData = [ + { childName: 'cats', name: 'Cats' }, + { childName: 'dogs', name: 'Dogs' }, + { childName: 'birds', name: 'Birds' } + ]; + const data1: Data[] = [ + { x: 'Sunday', y: 6 }, + { x: 'Monday', y: 2 }, + { x: 'Tuesday', y: 8 }, + { x: 'Wednesday', y: 15 }, + { x: 'Thursday', y: 6 }, + { x: 'Friday', y: 2 }, + { x: 'Saturday', y: 0 } + ]; + const data2: Data[] = [ + { x: 'Sunday', y: 4 }, + { x: 'Monday', y: 5 }, + { x: 'Tuesday', y: 7 }, + { x: 'Wednesday', y: 6 }, + { x: 'Thursday', y: 10 }, + { x: 'Friday', y: 3 }, + { x: 'Saturday', y: 5 } + ]; + const data3: Data[] = [ + { x: 'Sunday', y: 8 }, + { x: 'Monday', y: 18 }, + { x: 'Tuesday', y: 14 }, + { x: 'Wednesday', y: 8 }, + { x: 'Thursday', y: 6 }, + { x: 'Friday', y: 8 }, + { x: 'Saturday', y: 12 } + ]; + + return ( +
    +
    + `${datum.y !== null ? datum.y : 'no data'}`} + labelComponent={ datum.x} />} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom-left" + height={225} + name="chart5" + padding={{ + bottom: 75, // Adjusted to accomodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 30 }} + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + + + + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/ChartStyles.ts b/packages/react-charts/src/victory/components/ChartTheme/ChartStyles.ts new file mode 100644 index 00000000000..06af3473a18 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/ChartStyles.ts @@ -0,0 +1,56 @@ +import { CommonStyles } from './styles/common-styles'; +import { BulletStyles } from './styles/bullet-styles'; +import { BoxPlotTooltipStyles } from './styles/box-plot-tooltip-styles'; +import { DonutStyles } from './styles/donut-styles'; +import { DonutUtilizationStyles } from './styles/donut-utilization-styles'; +import { LegendTooltipStyles } from './styles/legend-tooltip-styles'; +import { ScatterStyles } from './styles/scatter-styles'; + +/** + * Common styles + * + * @private Not intended as public API and subject to change + */ +export const ChartCommonStyles = CommonStyles; + +/** + * Bullet styles + * + * @private Not intended as public API and subject to change + */ +export const ChartBulletStyles = BulletStyles; + +/** + * Legend tooltip styles + * + * @private Not intended as public API and subject to change + */ +export const ChartBoxPlotTooltipStyles = BoxPlotTooltipStyles; + +/** + * Donut styles + * + * @private Not intended as public API and subject to change + */ +export const ChartDonutStyles = DonutStyles; + +/** + * Donut utilization styles + * + * @private Not intended as public API and subject to change + */ +export const ChartDonutUtilizationStyles = DonutUtilizationStyles; + +/** + * Legend tooltip styles + * + * @private Not intended as public API and subject to change + */ +export const ChartLegendTooltipStyles = LegendTooltipStyles; + +/** + * Scatter styles + * + * @private Not intended as public API and subject to change + */ +export const ChartScatterStyles = ScatterStyles; diff --git a/packages/react-charts/src/victory/components/ChartTheme/ChartTheme.ts b/packages/react-charts/src/victory/components/ChartTheme/ChartTheme.ts new file mode 100644 index 00000000000..3bc3a3ac788 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/ChartTheme.ts @@ -0,0 +1,56 @@ +import { VictoryThemeDefinition } from 'victory-core'; + +/** + * Chart component theme definition + * + * @private Not intended as public API and subject to change + */ +export interface ChartComponentThemeDefinitionInterface { + axis?: VictoryThemeDefinition; + bullet?: VictoryThemeDefinition; + bulletComparativeErrorMeasure?: VictoryThemeDefinition; + bulletComparativeMeasure?: VictoryThemeDefinition; + bulletComparativeWarningMeasure: VictoryThemeDefinition; + bulletGroupTitle?: VictoryThemeDefinition; + bulletPrimaryDotMeasure?: VictoryThemeDefinition; + bulletPrimaryNegativeMeasure?: VictoryThemeDefinition; + bulletPrimarySegmentedMeasure?: VictoryThemeDefinition; + bulletQualitativeRange?: VictoryThemeDefinition; + donut?: VictoryThemeDefinition; + donutThresholdDynamic?: VictoryThemeDefinition; + donutThresholdStatic?: VictoryThemeDefinition; + donutUtilization?: VictoryThemeDefinition; + label?: { + backgroundStyle?: { + fill?: string; + }; + style?: { + fill?: string; + stroke?: string; + }; + }; + threshold?: VictoryThemeDefinition; +} + +/** + * Chart theme definition + * + * Note: Victory incorrectly typed ThemeBaseProps.padding as number instead of PaddingProps + * + * @public + */ +export interface ChartThemeDefinitionInterface extends VictoryThemeDefinition {} + +/** + * Chart theme definition + * + * @public + */ +export type ChartThemeDefinition = ChartThemeDefinitionInterface; + +/** + * Chart component theme definition + * + * @private Not intended as public API and subject to change + */ +export type ChartComponentThemeDefinition = ChartComponentThemeDefinitionInterface; diff --git a/packages/react-charts/src/victory/components/ChartTheme/ChartThemeColor.ts b/packages/react-charts/src/victory/components/ChartTheme/ChartThemeColor.ts new file mode 100644 index 00000000000..2b15dfd0aea --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/ChartThemeColor.ts @@ -0,0 +1,55 @@ +interface ChartThemeColorInterface { + blue: string; + teal: string; + default: string; + yellow: string; + gray: string; + green: string; + multi: string; + multiOrdered: string; + multiUnordered: string; + orange: string; + purple: string; + skeleton: string; +} + +/** + * The color family to be applied to a theme. For example, 'blue' represents an ordered list of colors + * (i.e., a color scale) composed of the blue color family defined by PatternFly core. + * + * For example, the 'blue' color scale looks like: + * + * chart_color_blue_100 + * chart_color_blue_200 + * chart_color_blue_300 + * chart_color_blue_400 + * chart_color_blue_500 + * + * In this case, the chart_color_blue_100 value would be applied to the first data point in a chart. + * The chart_color_blue_200 value would be applied to the second data point in a chart. And so on... + * + * If legend data is provided to a chart, those colors would be synced with the legend as well. + * + * The 'multiOrdered' color family is intended for ordered charts; donut, pie, bar, & stack + * The 'multiUnordered' color family is intended for unordered charts; area & line + * The 'multi' defaults to the 'multiOrdered' color family + * + * Note: These values are not intended to be applied directly as a component's fill style. For example, "multi" would + * not be a valid fill color. Please use chart variables from PatternFly core (e.g., via the react-charts package) + * + * @public + */ +export const ChartThemeColor: ChartThemeColorInterface = { + blue: 'blue', + teal: 'teal', + default: 'blue', + yellow: 'yellow', + gray: 'gray', + green: 'green', + multi: 'multi', + multiOrdered: 'multi-ordered', + multiUnordered: 'multi-unordered', + orange: 'orange', + purple: 'purple', + skeleton: 'skeleton' +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/ChartThemeTypes.ts b/packages/react-charts/src/victory/components/ChartTheme/ChartThemeTypes.ts new file mode 100644 index 00000000000..4fd0a3d5fa7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/ChartThemeTypes.ts @@ -0,0 +1,16 @@ +import { ChartComponentThemeDefinition, ChartThemeDefinition } from './ChartTheme'; +import { BaseComponentTheme, BaseTheme } from './themes/base-theme'; + +/** + * Base theme + * + * @private Not intended as public API and subject to change + */ +export const ChartBaseTheme: ChartThemeDefinition = BaseTheme; + +/** + * Base component theme + * + * @private Not intended as public API and subject to change + */ +export const ChartBaseComponentTheme: ChartComponentThemeDefinition = BaseComponentTheme; diff --git a/packages/react-charts/src/victory/components/ChartTheme/examples/ChartTheme.md b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartTheme.md new file mode 100644 index 00000000000..04d7276771d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartTheme.md @@ -0,0 +1,94 @@ +--- +id: Colors for charts +section: components +subsection: charts +hideDarkMode: true +--- + +import { + Chart, + ChartArea, + ChartAxis, + ChartBar, + ChartDonut, + ChartGroup, + ChartLegend, + ChartLine, + ChartStack, + ChartThemeColor, + ChartThreshold, + ChartTooltip, + ChartVoronoiContainer, + getCustomTheme +} from '@patternfly/react-charts/victory'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_teal_300 from '@patternfly/react-tokens/dist/esm/chart_color_teal_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; +import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Green + +This demonstrates how to apply basic theme colors. + +```ts file = "ChartThemeGreen.tsx" + +``` + +### Multi-color (ordered) + +This demonstrates how to apply theme colors for ordered charts like bar, donut, pie, and stack. + +```ts file = "ChartThemeMultiColorOrdered.tsx" + +``` + +### Multi color (unordered) + +This demonstrates how to apply theme colors for unordered charts like area, line, and sparkline. + +```ts file = "ChartThemeMultiColorUnordered.tsx" + +``` + +### Custom color scale + +This demonstrates an alternate way of applying a custom color scale and fill colors to individual charts. + +```ts file = "ChartThemeCustomColorScale.tsx" + +``` + +### Custom stroke color + +This demonstrates an alternate way of applying custom stroke and fill colors to a threshold chart. + +```ts file = "ChartThemeCustomStrokeColor.tsx" + +``` + +### Custom theme + +This demonstrates custom theme properties, which may be applied across multiple charts. + +```ts file = "ChartThemeCustomTheme.tsx" + +``` + +## Documentation + +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- The `theme` and `themeColor` props should be applied at the most top level component +- Use `ChartGroup` to apply theme color scales and other properties to multiple components + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the components used in the examples above, Victory pass-thru props are also documented here: + +- For theme props, see [VictoryTheme](https://formidable.com/open-source/victory/docs/victory-theme) diff --git a/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomColorScale.tsx b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomColorScale.tsx new file mode 100644 index 00000000000..bc40b1952c9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomColorScale.tsx @@ -0,0 +1,109 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartLegend, + ChartStack, + ChartThemeColor, + ChartTooltip +} from '@patternfly/react-charts/victory'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; +import chart_color_purple_300 from '@patternfly/react-tokens/dist/esm/chart_color_purple_300'; + +interface PetData { + name?: string; + symbol?: { fill: string }; + x?: string; + y?: number; + label?: string; +} + +export const ChartThemeCustomColorScale: React.FunctionComponent = () => { + const data1: PetData[] = [ + { + name: 'Cats', + symbol: { fill: chart_color_blue_300.var } + }, + { + name: 'Dogs', + symbol: { fill: chart_color_yellow_300.var } + }, + { + name: 'Birds', + symbol: { fill: chart_color_green_300.var } + }, + { + name: 'Mice', + symbol: { fill: chart_color_purple_300.var } + } + ]; + + const data2: PetData[] = [ + { name: 'Cats', x: '2015', y: 1, label: 'Cats: 1' }, + { name: 'Cats', x: '2016', y: 2, label: 'Cats: 2' }, + { name: 'Cats', x: '2017', y: 5, label: 'Cats: 5' }, + { name: 'Cats', x: '2018', y: 3, label: 'Cats: 3' } + ]; + + const data3: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2, label: 'Dogs: 2' }, + { name: 'Dogs', x: '2016', y: 1, label: 'Dogs: 1' }, + { name: 'Dogs', x: '2017', y: 7, label: 'Dogs: 7' }, + { name: 'Dogs', x: '2018', y: 4, label: 'Dogs: 4' } + ]; + + const data4: PetData[] = [ + { name: 'Birds', x: '2015', y: 4, label: 'Birds: 4' }, + { name: 'Birds', x: '2016', y: 4, label: 'Birds: 4' }, + { name: 'Birds', x: '2017', y: 9, label: 'Birds: 9' }, + { name: 'Birds', x: '2018', y: 7, label: 'Birds: 7' } + ]; + + const data5: PetData[] = [ + { name: 'Mice', x: '2015', y: 3, label: 'Mice: 3' }, + { name: 'Mice', x: '2016', y: 3, label: 'Mice: 3' }, + { name: 'Mice', x: '2017', y: 8, label: 'Mice: 8' }, + { name: 'Mice', x: '2018', y: 5, label: 'Mice: 5' } + ]; + + return ( +
    + } + legendPosition="bottom-left" + height={275} + name="chart4" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.multiOrdered} + width={450} + > + + + + } /> + } /> + } /> + } /> + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomStrokeColor.tsx b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomStrokeColor.tsx new file mode 100644 index 00000000000..ce4d86275cd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomStrokeColor.tsx @@ -0,0 +1,97 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLine, + ChartThemeColor, + ChartThreshold, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; + +interface PetData { + name?: string; + symbol?: { fill: string; type: string }; + x?: string; + y?: number; +} + +export const ChartThemeCustomStrokeColor: React.FunctionComponent = () => { + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Birds' }, + { name: 'Mice' }, + { name: 'Cats Threshold', symbol: { fill: chart_color_blue_300.var, type: 'threshold' } } + ]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + + const data3: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + const data4: PetData[] = [ + { name: 'Cats Threshold', x: '2015', y: 5 }, + { name: 'Cats Threshold', x: '2016', y: 5 }, + { name: 'Cats Threshold', x: '2016', y: 6 }, + { name: 'Cats Threshold', x: '2017', y: 6 }, + { name: 'Cats Threshold', x: '2018', y: 6 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendPosition="bottom" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart5" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.multiUnordered} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomTheme.tsx b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomTheme.tsx new file mode 100644 index 00000000000..425fd4dc36b --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeCustomTheme.tsx @@ -0,0 +1,119 @@ +import { + Chart, + ChartBar, + ChartAxis, + ChartGroup, + ChartThemeColor, + ChartVoronoiContainer, + getCustomTheme +} from '@patternfly/react-charts/victory'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_teal_300 from '@patternfly/react-tokens/dist/esm/chart_color_teal_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const ChartThemeCustomTheme: React.FunctionComponent = () => { + const colorScale = [ + chart_color_blue_300.var, + chart_color_green_300.var, + chart_color_teal_300.var, + chart_color_yellow_300.var + ]; + + const layoutProps = { + padding: { + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + } + }; + + // Victory theme properties only + const themeProps = { + bar: { + colorScale, + ...layoutProps + }, + chart: { + colorScale, + ...layoutProps + }, + group: { + colorScale, + ...layoutProps + }, + legend: { + colorScale + } + }; + + // Applies theme color and variant to base theme + const myCustomTheme = getCustomTheme(ChartThemeColor.default, themeProps); + + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domain={{ y: [0, 9] }} + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + name="chart6" + theme={myCustomTheme} + width={600} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeGreen.tsx b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeGreen.tsx new file mode 100644 index 00000000000..59b3bb0b4c3 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeGreen.tsx @@ -0,0 +1,94 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLine, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + symbol?: { type: string }; + x?: string; + y?: number; +} + +export const ChartThemeGreen: React.FunctionComponent = () => { + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendPosition="bottom" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart1" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.green} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeMultiColorOrdered.tsx b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeMultiColorOrdered.tsx new file mode 100644 index 00000000000..8727fbe9f74 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeMultiColorOrdered.tsx @@ -0,0 +1,43 @@ +import { ChartDonut, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartThemeMultiColorOrdered: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart2" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + title="100" + themeColor={ChartThemeColor.multiOrdered} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeMultiColorUnordered.tsx b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeMultiColorUnordered.tsx new file mode 100644 index 00000000000..1dcf6e38b9b --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/examples/ChartThemeMultiColorUnordered.tsx @@ -0,0 +1,75 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const ChartThemeMultiColorUnordered: React.FunctionComponent = () => { + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 3 }, + { name: 'Dogs', x: '2017', y: 4 }, + { name: 'Dogs', x: '2018', y: 5 }, + { name: 'Dogs', x: '2019', y: 6 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 1 }, + { name: 'Birds', x: '2016', y: 2 }, + { name: 'Birds', x: '2017', y: 3 }, + { name: 'Birds', x: '2018', y: 2 }, + { name: 'Birds', x: '2019', y: 4 } + ]; + + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={200} + maxDomain={{ y: 9 }} + name="chart3" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={ChartThemeColor.multiUnordered} + width={800} + > + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/styles/box-plot-tooltip-styles.ts b/packages/react-charts/src/victory/components/ChartTheme/styles/box-plot-tooltip-styles.ts new file mode 100644 index 00000000000..be0f751bc27 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/styles/box-plot-tooltip-styles.ts @@ -0,0 +1,17 @@ +import t_global_font_weight_heading_bold from '@patternfly/react-tokens/dist/esm/t_global_font_weight_heading_bold'; +import chart_voronoi_labels_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Fill'; + +/** + * Box plot tooltip styles + * + * @private Not intended as public API and subject to change + */ +export const BoxPlotTooltipStyles = { + flyout: { + padding: 40 + }, + label: { + fill: chart_voronoi_labels_Fill.var, + fontWeight: t_global_font_weight_heading_bold.value + } as any +}; diff --git a/packages/react-charts/src/components/ChartTheme/styles/bullet-styles.ts b/packages/react-charts/src/victory/components/ChartTheme/styles/bullet-styles.ts similarity index 82% rename from packages/react-charts/src/components/ChartTheme/styles/bullet-styles.ts rename to packages/react-charts/src/victory/components/ChartTheme/styles/bullet-styles.ts index a8ef9efb97e..2978bed08e0 100644 --- a/packages/react-charts/src/components/ChartTheme/styles/bullet-styles.ts +++ b/packages/react-charts/src/victory/components/ChartTheme/styles/bullet-styles.ts @@ -1,9 +1,10 @@ -/* eslint-disable camelcase */ import chart_bullet_axis_tick_count from '@patternfly/react-tokens/dist/esm/chart_bullet_axis_tick_count'; import chart_bullet_comparative_measure_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_Width'; import chart_bullet_comparative_measure_error_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_error_Width'; import chart_bullet_comparative_measure_warning_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_warning_Width'; +import chart_bullet_label_grouptitle_Fill from '@patternfly/react-tokens/dist/esm/chart_bullet_label_grouptitle_Fill'; import chart_bullet_label_subtitle_Fill from '@patternfly/react-tokens/dist/esm/chart_bullet_label_subtitle_Fill'; +import chart_bullet_label_title_Fill from '@patternfly/react-tokens/dist/esm/chart_bullet_label_title_Fill'; import chart_bullet_primary_measure_dot_size from '@patternfly/react-tokens/dist/esm/chart_bullet_primary_measure_dot_size'; import chart_bullet_primary_measure_segmented_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_primary_measure_segmented_Width'; import chart_bullet_qualitative_range_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_qualitative_range_Width'; @@ -11,7 +12,11 @@ import chart_global_FontSize_2xl from '@patternfly/react-tokens/dist/esm/chart_g import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; import chart_global_FontSize_lg from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_lg'; -// Bullet styles +/** + * Bullet styles + * + * @private Not intended as public API and subject to change + */ export const BulletStyles = { axisTickCount: chart_bullet_axis_tick_count.value, comparativeMeasureErrorWidth: chart_bullet_comparative_measure_error_Width.value, @@ -20,15 +25,17 @@ export const BulletStyles = { label: { groupTitle: { // Victory props only + fill: chart_bullet_label_grouptitle_Fill.var, fontSize: chart_global_FontSize_2xl.value }, subTitle: { // Victory props only - fill: chart_bullet_label_subtitle_Fill.value, + fill: chart_bullet_label_subtitle_Fill.var, fontSize: chart_global_FontSize_sm.value }, title: { // Victory props only + fill: chart_bullet_label_title_Fill.var, fontSize: chart_global_FontSize_lg.value } }, diff --git a/packages/react-charts/src/victory/components/ChartTheme/styles/common-styles.ts b/packages/react-charts/src/victory/components/ChartTheme/styles/common-styles.ts new file mode 100644 index 00000000000..05a5d3db21e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/styles/common-styles.ts @@ -0,0 +1,31 @@ +import chart_global_FontFamily from '@patternfly/react-tokens/dist/esm/chart_global_FontFamily'; +import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; +import chart_global_label_Margin from '@patternfly/react-tokens/dist/esm/chart_global_label_Margin'; +import chart_global_label_Fill from '@patternfly/react-tokens/dist/esm/chart_global_label_Fill'; +import chart_global_letter_spacing from '@patternfly/react-tokens/dist/esm/chart_global_letter_spacing'; +import chart_legend_Margin from '@patternfly/react-tokens/dist/esm/chart_legend_Margin'; +import chart_legend_position from '@patternfly/react-tokens/dist/esm/chart_legend_position'; + +// Typography +const TYPOGRAPHY_FONT_FAMILY = chart_global_FontFamily.var.replace(/"/g, "'"); // Well-formed XML +const TYPOGRAPHY_LETTER_SPACING = chart_global_letter_spacing.var; +const TYPOGRAPHY_FONT_SIZE = chart_global_FontSize_sm.value; + +/** + * Common styles + * + * @private Not intended as public API and subject to change + */ +export const CommonStyles = { + label: { + fontFamily: TYPOGRAPHY_FONT_FAMILY, + fontSize: TYPOGRAPHY_FONT_SIZE, + letterSpacing: TYPOGRAPHY_LETTER_SPACING, + margin: chart_global_label_Margin.value, + fill: chart_global_label_Fill.var + }, + legend: { + margin: chart_legend_Margin.value, + position: chart_legend_position.value + } +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/styles/donut-styles.ts b/packages/react-charts/src/victory/components/ChartTheme/styles/donut-styles.ts new file mode 100644 index 00000000000..8b8f88f39e4 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/styles/donut-styles.ts @@ -0,0 +1,26 @@ +import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; +import chart_global_FontSize_2xl from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_2xl'; +import chart_donut_label_subtitle_Fill from '@patternfly/react-tokens/dist/esm/chart_donut_label_subtitle_Fill'; +import chart_donut_label_title_Fill from '@patternfly/react-tokens/dist/esm/chart_donut_label_title_Fill'; +import chart_donut_label_subtitle_position from '@patternfly/react-tokens/dist/esm/chart_donut_label_subtitle_position'; + +/** + * Donut styles + * + * @private Not intended as public API and subject to change + */ +export const DonutStyles = { + label: { + subTitle: { + // Victory props only + fill: chart_donut_label_subtitle_Fill.var, + fontSize: chart_global_FontSize_sm.value + }, + subTitlePosition: chart_donut_label_subtitle_position.value, + title: { + // Victory props only + fill: chart_donut_label_title_Fill.var, + fontSize: chart_global_FontSize_2xl.value + } + } +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/styles/donut-utilization-styles.ts b/packages/react-charts/src/victory/components/ChartTheme/styles/donut-utilization-styles.ts new file mode 100644 index 00000000000..b5ec3725ff8 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/styles/donut-utilization-styles.ts @@ -0,0 +1,13 @@ +import chart_donut_threshold_warning_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_warning_Color'; +import chart_donut_threshold_danger_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_danger_Color'; + +/** + * Donut utilization styles + * + * @private Not intended as public API and subject to change + */ +export const DonutUtilizationStyles = { + thresholds: { + colorScale: [chart_donut_threshold_warning_Color.var, chart_donut_threshold_danger_Color.var] + } +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/styles/legend-tooltip-styles.ts b/packages/react-charts/src/victory/components/ChartTheme/styles/legend-tooltip-styles.ts new file mode 100644 index 00000000000..2d54cf7f2ab --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/styles/legend-tooltip-styles.ts @@ -0,0 +1,17 @@ +import t_global_font_weight_heading_bold from '@patternfly/react-tokens/dist/esm/t_global_font_weight_heading_bold'; +import chart_voronoi_labels_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Fill'; + +/** + * Legend tooltip styles + * + * @private Not intended as public API and subject to change + */ +export const LegendTooltipStyles = { + flyout: { + padding: 40 + }, + label: { + fill: chart_voronoi_labels_Fill.var, + fontWeight: t_global_font_weight_heading_bold.value + } as any +}; diff --git a/packages/react-charts/src/components/ChartTheme/styles/scatter-styles.ts b/packages/react-charts/src/victory/components/ChartTheme/styles/scatter-styles.ts similarity index 77% rename from packages/react-charts/src/components/ChartTheme/styles/scatter-styles.ts rename to packages/react-charts/src/victory/components/ChartTheme/styles/scatter-styles.ts index 5eb07a4b043..c41a20a812f 100644 --- a/packages/react-charts/src/components/ChartTheme/styles/scatter-styles.ts +++ b/packages/react-charts/src/victory/components/ChartTheme/styles/scatter-styles.ts @@ -1,8 +1,11 @@ -/* eslint-disable camelcase */ import chart_scatter_active_size from '@patternfly/react-tokens/dist/esm/chart_scatter_active_size'; import chart_scatter_size from '@patternfly/react-tokens/dist/esm/chart_scatter_size'; -// Donut styles +/** + * Scatter styles + * + * @private Not intended as public API and subject to change + */ export const ScatterStyles = { activeSize: chart_scatter_active_size.value, size: chart_scatter_size.value diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/base-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/base-theme.ts new file mode 100644 index 00000000000..02fdd77d2b1 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/base-theme.ts @@ -0,0 +1,569 @@ +import chart_global_FontFamily from '@patternfly/react-tokens/dist/esm/chart_global_FontFamily'; +import chart_global_letter_spacing from '@patternfly/react-tokens/dist/esm/chart_global_letter_spacing'; +import chart_global_FontSize_sm from '@patternfly/react-tokens/dist/esm/chart_global_FontSize_sm'; +import chart_global_label_Padding from '@patternfly/react-tokens/dist/esm/chart_global_label_Padding'; +import chart_global_label_stroke from '@patternfly/react-tokens/dist/esm/chart_global_label_stroke'; +import chart_global_label_text_anchor from '@patternfly/react-tokens/dist/esm/chart_global_label_text_anchor'; +import chart_global_label_Fill from '@patternfly/react-tokens/dist/esm/chart_global_label_Fill'; +import chart_global_layout_Padding from '@patternfly/react-tokens/dist/esm/chart_global_layout_Padding'; +import chart_global_layout_Height from '@patternfly/react-tokens/dist/esm/chart_global_layout_Height'; +import chart_global_layout_Width from '@patternfly/react-tokens/dist/esm/chart_global_layout_Width'; +import chart_global_stroke_line_cap from '@patternfly/react-tokens/dist/esm/chart_global_stroke_line_cap'; +import chart_global_stroke_line_join from '@patternfly/react-tokens/dist/esm/chart_global_stroke_line_join'; +import chart_area_data_Fill from '@patternfly/react-tokens/dist/esm/chart_area_data_Fill'; +import chart_area_Opacity from '@patternfly/react-tokens/dist/esm/chart_area_Opacity'; +import chart_area_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_area_stroke_Width'; +import chart_axis_axis_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_axis_axis_stroke_Width'; +import chart_axis_axis_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_axis_stroke_Color'; +import chart_axis_axis_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_axis_Fill'; +import chart_axis_axis_label_Padding from '@patternfly/react-tokens/dist/esm/chart_axis_axis_label_Padding'; +import chart_axis_axis_label_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_axis_label_stroke_Color'; +import chart_axis_grid_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_grid_Fill'; +import chart_axis_grid_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_axis_grid_PointerEvents'; +import chart_axis_tick_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_tick_Fill'; +import chart_axis_tick_Size from '@patternfly/react-tokens/dist/esm/chart_axis_tick_Size'; +import chart_axis_tick_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_tick_stroke_Color'; +import chart_axis_tick_Width from '@patternfly/react-tokens/dist/esm/chart_axis_tick_Width'; +import chart_axis_tick_label_Fill from '@patternfly/react-tokens/dist/esm/chart_axis_tick_label_Fill'; +import chart_bar_Width from '@patternfly/react-tokens/dist/esm/chart_bar_Width'; +import chart_bar_data_stroke from '@patternfly/react-tokens/dist/esm/chart_bar_data_stroke'; +import chart_bar_data_Fill from '@patternfly/react-tokens/dist/esm/chart_bar_data_Fill'; +import chart_bar_data_Padding from '@patternfly/react-tokens/dist/esm/chart_bar_data_Padding'; +import chart_bar_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bar_data_stroke_Width'; +import chart_boxplot_max_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_max_Padding'; +import chart_boxplot_max_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_boxplot_max_stroke_Color'; +import chart_boxplot_max_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_max_stroke_Width'; +import chart_boxplot_median_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_median_Padding'; +import chart_boxplot_median_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_boxplot_median_stroke_Color'; +import chart_boxplot_median_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_median_stroke_Width'; +import chart_boxplot_min_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_min_Padding'; +import chart_boxplot_min_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_min_stroke_Width'; +import chart_boxplot_min_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_boxplot_min_stroke_Color'; +import chart_boxplot_lower_quartile_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_lower_quartile_Padding'; +import chart_boxplot_lower_quartile_Fill from '@patternfly/react-tokens/dist/esm/chart_boxplot_lower_quartile_Fill'; +import chart_boxplot_upper_quartile_Padding from '@patternfly/react-tokens/dist/esm/chart_boxplot_upper_quartile_Padding'; +import chart_boxplot_upper_quartile_Fill from '@patternfly/react-tokens/dist/esm/chart_boxplot_upper_quartile_Fill'; +import chart_boxplot_box_Width from '@patternfly/react-tokens/dist/esm/chart_boxplot_box_Width'; +import chart_candelstick_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_candelstick_data_stroke_Width'; +import chart_candelstick_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_candelstick_data_stroke_Color'; +import chart_candelstick_candle_positive_Color from '@patternfly/react-tokens/dist/esm/chart_candelstick_candle_positive_Color'; +import chart_candelstick_candle_negative_Color from '@patternfly/react-tokens/dist/esm/chart_candelstick_candle_negative_Color'; +import chart_errorbar_BorderWidth from '@patternfly/react-tokens/dist/esm/chart_errorbar_BorderWidth'; +import chart_errorbar_data_Fill from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_Fill'; +import chart_errorbar_data_Opacity from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_Opacity'; +import chart_errorbar_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_stroke_Width'; +import chart_errorbar_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_errorbar_data_stroke_Color'; +import chart_legend_gutter_Width from '@patternfly/react-tokens/dist/esm/chart_legend_gutter_Width'; +import chart_legend_orientation from '@patternfly/react-tokens/dist/esm/chart_legend_orientation'; +import chart_legend_title_orientation from '@patternfly/react-tokens/dist/esm/chart_legend_title_orientation'; +import chart_legend_data_type from '@patternfly/react-tokens/dist/esm/chart_legend_data_type'; +import chart_legend_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_legend_data_stroke_Color'; +import chart_legend_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_legend_data_stroke_Width'; +import chart_legend_title_Padding from '@patternfly/react-tokens/dist/esm/chart_legend_title_Padding'; +import chart_line_data_Fill from '@patternfly/react-tokens/dist/esm/chart_line_data_Fill'; +import chart_line_data_Opacity from '@patternfly/react-tokens/dist/esm/chart_line_data_Opacity'; +import chart_line_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_line_data_stroke_Width'; +import chart_line_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_line_data_stroke_Color'; +import chart_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_pie_Padding'; +import chart_pie_data_Padding from '@patternfly/react-tokens/dist/esm/chart_pie_data_Padding'; +import chart_pie_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_pie_data_stroke_Width'; +import chart_pie_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_pie_data_stroke_Color'; +import chart_pie_labels_Padding from '@patternfly/react-tokens/dist/esm/chart_pie_labels_Padding'; +import chart_pie_Height from '@patternfly/react-tokens/dist/esm/chart_pie_Height'; +import chart_pie_Width from '@patternfly/react-tokens/dist/esm/chart_pie_Width'; +import chart_scatter_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_scatter_data_stroke_Color'; +import chart_scatter_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_scatter_data_stroke_Width'; +import chart_scatter_data_Opacity from '@patternfly/react-tokens/dist/esm/chart_scatter_data_Opacity'; +import chart_scatter_data_Fill from '@patternfly/react-tokens/dist/esm/chart_scatter_data_Fill'; +import chart_stack_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_stack_data_stroke_Width'; +import chart_tooltip_corner_radius from '@patternfly/react-tokens/dist/esm/chart_tooltip_corner_radius'; +import chart_tooltip_pointer_length from '@patternfly/react-tokens/dist/esm/chart_tooltip_pointer_length'; +import chart_tooltip_Fill from '@patternfly/react-tokens/dist/esm/chart_tooltip_Fill'; +import chart_tooltip_flyoutStyle_corner_radius from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_corner_radius'; +import chart_tooltip_flyoutStyle_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_stroke_Width'; +import chart_tooltip_flyoutStyle_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_PointerEvents'; +import chart_tooltip_flyoutStyle_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_stroke_Color'; +import chart_tooltip_flyoutStyle_Fill from '@patternfly/react-tokens/dist/esm/chart_tooltip_flyoutStyle_Fill'; +import chart_tooltip_pointer_Width from '@patternfly/react-tokens/dist/esm/chart_tooltip_pointer_Width'; +import chart_tooltip_Padding from '@patternfly/react-tokens/dist/esm/chart_tooltip_Padding'; +import chart_tooltip_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_tooltip_PointerEvents'; +import chart_voronoi_data_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_data_Fill'; +import chart_voronoi_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_voronoi_data_stroke_Color'; +import chart_voronoi_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_voronoi_data_stroke_Width'; +import chart_voronoi_labels_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Fill'; +import chart_voronoi_labels_Padding from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Padding'; +import chart_voronoi_labels_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_PointerEvents'; +import chart_voronoi_flyout_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_stroke_Width'; +import chart_voronoi_flyout_PointerEvents from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_PointerEvents'; +import chart_voronoi_flyout_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_stroke_Color'; +import chart_voronoi_flyout_stroke_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_stroke_Fill'; +import chart_donut_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_pie_Height'; +import chart_donut_pie_angle_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_pie_angle_Padding'; +import chart_donut_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_pie_Padding'; +import chart_donut_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_pie_Width'; +import chart_donut_pie_data_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_donut_pie_data_stroke_Color'; +import chart_donut_pie_data_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_donut_pie_data_stroke_Width'; +import chart_donut_threshold_dynamic_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_dynamic_pie_Height'; +import chart_donut_threshold_dynamic_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_dynamic_pie_Padding'; +import chart_donut_threshold_dynamic_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_dynamic_pie_Width'; +import chart_donut_threshold_static_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_Height'; +import chart_donut_threshold_static_pie_angle_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_angle_Padding'; +import chart_donut_threshold_static_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_Padding'; +import chart_donut_threshold_static_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_static_pie_Width'; +import chart_donut_utilization_dynamic_pie_Height from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_Height'; +import chart_donut_utilization_dynamic_pie_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_Padding'; +import chart_donut_utilization_dynamic_pie_angle_Padding from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_angle_Padding'; +import chart_donut_utilization_dynamic_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut_utilization_dynamic_pie_Width'; +import chart_threshold_stroke_dash_array from '@patternfly/react-tokens/dist/esm/chart_threshold_stroke_dash_array'; +import chart_threshold_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_threshold_stroke_Width'; +import chart_bullet_Height from '@patternfly/react-tokens/dist/esm/chart_bullet_Height'; +import chart_bullet_bar_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_bar_stroke_Color'; +import chart_bullet_bar_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_bar_stroke_Width'; +import chart_bullet_comparative_measure_error_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_error_stroke_Width'; +import chart_bullet_comparative_measure_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_stroke_Width'; +import chart_bullet_comparative_measure_warning_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_warning_stroke_Width'; +import chart_bullet_group_title_divider_stroke_Width from '@patternfly/react-tokens/dist/esm/chart_bullet_group_title_divider_stroke_Width'; +import { ChartComponentThemeDefinition, ChartThemeDefinition } from '../ChartTheme'; + +// Note: Values must be in pixles + +// Typography +// +// Note: Victory's approximateTextSize function uses specific character widths and does not work with font variables +// See https://github.com/patternfly/patternfly-react/issues/5300 and https://github.com/patternfly/patternfly-react/pull/5301 +const TYPOGRAPHY_FONT_FAMILY = chart_global_FontFamily.var.replace(/"/g, "'"); // Well-formed XML +const TYPOGRAPHY_LETTER_SPACING = chart_global_letter_spacing.value; +const TYPOGRAPHY_FONT_SIZE = chart_global_FontSize_sm.value; + +// Labels +const LABEL_PROPS = { + fontFamily: TYPOGRAPHY_FONT_FAMILY, + fontSize: TYPOGRAPHY_FONT_SIZE, + letterSpacing: TYPOGRAPHY_LETTER_SPACING, + padding: chart_global_label_Padding.value, + stroke: chart_global_label_stroke.var, + fill: chart_global_label_Fill.var +}; + +const LABEL_CENTERED_PROPS = { + ...LABEL_PROPS, + textAnchor: chart_global_label_text_anchor.value +}; + +// Layout +const LAYOUT_PROPS = { + padding: chart_global_layout_Padding.value, + height: chart_global_layout_Height.value, + width: chart_global_layout_Width.value +}; + +// Strokes +const STROKE_LINE_CAP = chart_global_stroke_line_cap.value; +const STROKE_LINE_JOIN = chart_global_stroke_line_join.value; + +/** + * Base theme containing Victory properties only + * + * @private Not intended as public API and subject to change + */ +export const BaseTheme: ChartThemeDefinition = { + area: { + ...LAYOUT_PROPS, + style: { + data: { + fill: chart_area_data_Fill.var, + fillOpacity: chart_area_Opacity.var, + // Omit stroke to add a line border from color scale + // stroke: chart_global_label_stroke_color.value, + strokeWidth: chart_area_stroke_Width.value + }, + labels: LABEL_CENTERED_PROPS + } + }, + axis: { + ...LAYOUT_PROPS, + style: { + axis: { + fill: chart_axis_axis_Fill.var, + strokeWidth: chart_axis_axis_stroke_Width.value, + stroke: chart_axis_axis_stroke_Color.var, + strokeLinecap: STROKE_LINE_CAP, + strokeLinejoin: STROKE_LINE_JOIN + }, + axisLabel: { + ...LABEL_CENTERED_PROPS, + padding: chart_axis_axis_label_Padding.value, + stroke: chart_axis_axis_label_stroke_Color.var + }, + grid: { + fill: chart_axis_grid_Fill.var, + stroke: 'transparent', + pointerEvents: chart_axis_grid_PointerEvents.value, + strokeLinecap: STROKE_LINE_CAP, + strokeLinejoin: STROKE_LINE_JOIN + }, + ticks: { + fill: chart_axis_tick_Fill.var, + size: chart_axis_tick_Size.value, + stroke: chart_axis_tick_stroke_Color.var, + strokeLinecap: STROKE_LINE_CAP, + strokeLinejoin: STROKE_LINE_JOIN, + strokeWidth: chart_axis_tick_Width.value + }, + tickLabels: { + ...LABEL_PROPS, + fill: chart_axis_tick_label_Fill.var + } + } + }, + bar: { + ...LAYOUT_PROPS, + barWidth: chart_bar_Width.value, + style: { + data: { + fill: chart_bar_data_Fill.var, + padding: chart_bar_data_Padding.value, + stroke: chart_bar_data_stroke.var, + strokeWidth: chart_bar_data_stroke_Width.var + }, + labels: LABEL_PROPS + } + } as any, // Victory is missing barWidth + boxplot: { + ...LAYOUT_PROPS, + style: { + max: { + padding: chart_boxplot_max_Padding.value, + stroke: chart_boxplot_max_stroke_Color.var, + strokeWidth: chart_boxplot_max_stroke_Width.value + }, + maxLabels: LABEL_PROPS, + median: { + padding: chart_boxplot_median_Padding.value, + stroke: chart_boxplot_median_stroke_Color.var, + strokeWidth: chart_boxplot_median_stroke_Width.value + }, + medianLabels: LABEL_PROPS, + min: { + padding: chart_boxplot_min_Padding.value, + stroke: chart_boxplot_min_stroke_Color.var, + strokeWidth: chart_boxplot_min_stroke_Width.value + }, + minLabels: LABEL_PROPS, + q1: { + fill: chart_boxplot_lower_quartile_Fill.var, + padding: chart_boxplot_lower_quartile_Padding.value + }, + q1Labels: LABEL_PROPS, + q3: { + fill: chart_boxplot_upper_quartile_Fill.var, + padding: chart_boxplot_upper_quartile_Padding.value + }, + q3Labels: LABEL_PROPS + }, + boxWidth: chart_boxplot_box_Width.value + }, + candlestick: { + ...LAYOUT_PROPS, + candleColors: { + positive: chart_candelstick_candle_positive_Color.var, + negative: chart_candelstick_candle_negative_Color.var + }, + style: { + data: { + stroke: chart_candelstick_data_stroke_Color.var, + strokeWidth: chart_candelstick_data_stroke_Width.value + }, + labels: LABEL_CENTERED_PROPS + } + }, + chart: { + ...LAYOUT_PROPS + }, + errorbar: { + ...LAYOUT_PROPS, + borderWidth: chart_errorbar_BorderWidth.value, + style: { + data: { + fill: chart_errorbar_data_Fill.var, + opacity: chart_errorbar_data_Opacity.value, + stroke: chart_errorbar_data_stroke_Color.var, + strokeWidth: chart_errorbar_data_stroke_Width.value + }, + labels: LABEL_CENTERED_PROPS + } + }, + group: { + ...LAYOUT_PROPS + }, + legend: { + gutter: chart_legend_gutter_Width.value, + orientation: chart_legend_orientation.value, + titleOrientation: chart_legend_title_orientation.value, + style: { + data: { + type: chart_legend_data_type.value, + stroke: chart_legend_data_stroke_Color.var, + strokeWidth: chart_legend_data_stroke_Width.var + }, + labels: LABEL_PROPS, + title: { + ...LABEL_PROPS, + fontSize: TYPOGRAPHY_FONT_SIZE, + padding: chart_legend_title_Padding.value + } + } + }, + line: { + ...LAYOUT_PROPS, + style: { + data: { + fill: chart_line_data_Fill.var, + opacity: chart_line_data_Opacity.value, + stroke: chart_line_data_stroke_Color.var, + strokeWidth: chart_line_data_stroke_Width.value + }, + labels: LABEL_CENTERED_PROPS + } + }, + pie: { + padding: chart_pie_Padding.value, + style: { + data: { + padding: chart_pie_data_Padding.value, + stroke: chart_pie_data_stroke_Color.var, + strokeWidth: chart_pie_data_stroke_Width.var + }, + labels: { + ...LABEL_PROPS, + padding: chart_pie_labels_Padding.value + } + }, + height: chart_pie_Height.value, + width: chart_pie_Width.value + }, + scatter: { + ...LAYOUT_PROPS, + style: { + data: { + fill: chart_scatter_data_Fill.var, + opacity: chart_scatter_data_Opacity.value, + stroke: chart_scatter_data_stroke_Color.var, + strokeWidth: chart_scatter_data_stroke_Width.value + }, + labels: LABEL_CENTERED_PROPS + } + }, + stack: { + ...LAYOUT_PROPS, + style: { + data: { + strokeWidth: chart_stack_data_stroke_Width.value + } + } + } as any, // Victory is missing style + tooltip: { + cornerRadius: chart_tooltip_corner_radius.value, + flyoutPadding: chart_tooltip_Padding.value, + flyoutStyle: { + cornerRadius: chart_tooltip_flyoutStyle_corner_radius.value, + fill: chart_tooltip_flyoutStyle_Fill.var, // background + pointerEvents: chart_tooltip_flyoutStyle_PointerEvents.var, + stroke: chart_tooltip_flyoutStyle_stroke_Color.var, // border + strokeWidth: chart_tooltip_flyoutStyle_stroke_Width.var + }, + pointerLength: chart_tooltip_pointer_length.value, + pointerWidth: chart_tooltip_pointer_Width.value, + style: { + fill: chart_tooltip_Fill.var, // text + pointerEvents: chart_tooltip_PointerEvents.var + } + } as any, // Victory is missing cornerRadius and pointerWidth + voronoi: { + ...LAYOUT_PROPS, + style: { + data: { + fill: chart_voronoi_data_Fill.var, + stroke: chart_voronoi_data_stroke_Color.var, + strokeWidth: chart_voronoi_data_stroke_Width.value + }, + labels: { + ...LABEL_CENTERED_PROPS, + fill: chart_voronoi_labels_Fill.var, // text + padding: chart_voronoi_labels_Padding.value, + pointerEvents: chart_voronoi_labels_PointerEvents.value + }, + // Note: These properties override tooltip + flyout: { + fill: chart_voronoi_flyout_stroke_Fill.var, // background + pointerEvents: chart_voronoi_flyout_PointerEvents.var, + stroke: chart_voronoi_flyout_stroke_Color.var, // border + strokeWidth: chart_voronoi_flyout_stroke_Width.var + } + } + } +}; + +/** + * Base component theme + * + * @private Not intended as public API and subject to change + */ +export const BaseComponentTheme: ChartComponentThemeDefinition = { + axis: { + // TBD... + }, + bullet: { + chart: { + height: chart_bullet_Height.value + } + }, + bulletComparativeErrorMeasure: { + bar: { + height: chart_bullet_Height.value, + style: { + data: { + strokeWidth: chart_bullet_comparative_measure_error_stroke_Width.value + } + } + } + }, + bulletComparativeMeasure: { + bar: { + height: chart_bullet_Height.value, + style: { + data: { + strokeWidth: chart_bullet_comparative_measure_stroke_Width.value + } + } + } + }, + bulletComparativeWarningMeasure: { + bar: { + height: chart_bullet_Height.value, + style: { + data: { + strokeWidth: chart_bullet_comparative_measure_warning_stroke_Width.value + } + } + } + }, + bulletGroupTitle: { + chart: { + padding: { + bottom: 0, + left: 0, + right: 0, + top: chart_global_layout_Padding.value + } as any // Victory incorrectly typed ThemeBaseProps.padding as number instead of PaddingProps + }, + line: { + style: { + data: { + strokeWidth: chart_bullet_group_title_divider_stroke_Width.value + } + } + } + }, + bulletPrimaryDotMeasure: { + group: { + height: chart_bullet_Height.value + }, + scatter: { + style: { + data: { + stroke: chart_bullet_bar_stroke_Color.var, + strokeWidth: chart_bullet_bar_stroke_Width.var + } + } + } + }, + bulletPrimaryNegativeMeasure: { + group: { + height: chart_bullet_Height.value + } + }, + bulletPrimarySegmentedMeasure: { + group: { + height: chart_bullet_Height.value + }, + bar: { + style: { + data: { + stroke: chart_bullet_bar_stroke_Color.var, + strokeWidth: chart_bullet_bar_stroke_Width.var + } + } + } + }, + bulletQualitativeRange: { + group: { + height: chart_bullet_Height.value + } + }, + donut: { + pie: { + height: chart_donut_pie_Height.value, + padding: chart_donut_pie_Padding.value, + padAngle: chart_donut_pie_angle_Padding.value, + width: chart_donut_pie_Width.value, + style: { + data: { + stroke: chart_donut_pie_data_stroke_Color.var, + strokeWidth: chart_donut_pie_data_stroke_Width.var + } + } + } as any // Victory is missing padAngle + }, + donutThresholdDynamic: { + pie: { + height: chart_donut_threshold_dynamic_pie_Height.value, + padding: chart_donut_threshold_dynamic_pie_Padding.value, + width: chart_donut_threshold_dynamic_pie_Width.value, + style: { + data: { + stroke: chart_donut_pie_data_stroke_Color.var, + strokeWidth: chart_donut_pie_data_stroke_Width.var + } + } + } + }, + donutThresholdStatic: { + pie: { + height: chart_donut_threshold_static_pie_Height.value, + padAngle: chart_donut_threshold_static_pie_angle_Padding.value, + padding: chart_donut_threshold_static_pie_Padding.value, + width: chart_donut_threshold_static_pie_Width.value, + style: { + data: { + stroke: chart_donut_pie_data_stroke_Color.var, + strokeWidth: chart_donut_pie_data_stroke_Width.var + } + } + } as any // Victory is missing padAngle + }, + donutUtilization: { + pie: { + height: chart_donut_utilization_dynamic_pie_Height.value, + padding: chart_donut_utilization_dynamic_pie_Padding.value, + padAngle: chart_donut_utilization_dynamic_pie_angle_Padding.value, + width: chart_donut_utilization_dynamic_pie_Width.value, + style: { + data: { + stroke: chart_donut_pie_data_stroke_Color.var, + strokeWidth: chart_donut_pie_data_stroke_Width.var + } + } + } as any // Victory is missing padAngle + }, + threshold: { + line: { + style: { + data: { + strokeDasharray: chart_threshold_stroke_dash_array.value, + strokeWidth: chart_threshold_stroke_Width.value + } + } + } + } +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/color-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/color-theme.ts new file mode 100644 index 00000000000..9d910948597 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/color-theme.ts @@ -0,0 +1,249 @@ +import chart_donut_threshold_second_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_second_Color'; +import chart_donut_threshold_third_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_third_Color'; +import chart_donut_threshold_first_Color from '@patternfly/react-tokens/dist/esm/chart_donut_threshold_first_Color'; +import chart_axis_grid_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_grid_stroke_Color'; +import chart_axis_tick_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_axis_tick_stroke_Color'; +import chart_bullet_comparative_measure_error_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_error_Fill_Color'; +import chart_bullet_comparative_measure_error_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_error_stroke_Color'; +import chart_bullet_Height from '@patternfly/react-tokens/dist/esm/chart_bullet_Height'; +import chart_bullet_comparative_measure_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_Fill_Color'; +import chart_bullet_comparative_measure_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_stroke_Color'; +import chart_bullet_comparative_measure_warning_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_warning_Fill_Color'; +import chart_bullet_comparative_measure_warning_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_comparative_measure_warning_stroke_Color'; +import chart_bullet_group_title_divider_Fill_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_group_title_divider_Fill_Color'; +import chart_bullet_group_title_divider_stroke_Color from '@patternfly/react-tokens/dist/esm/chart_bullet_group_title_divider_stroke_Color'; +import chart_bullet_negative_measure_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_bullet_negative_measure_ColorScale_100'; +import chart_bullet_negative_measure_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_bullet_negative_measure_ColorScale_200'; +import chart_bullet_negative_measure_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_bullet_negative_measure_ColorScale_300'; +import chart_bullet_negative_measure_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_bullet_negative_measure_ColorScale_400'; +import chart_bullet_negative_measure_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_bullet_negative_measure_ColorScale_500'; +import chart_bullet_qualitative_range_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_bullet_qualitative_range_ColorScale_100'; +import chart_bullet_qualitative_range_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_bullet_qualitative_range_ColorScale_200'; +import chart_bullet_qualitative_range_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_bullet_qualitative_range_ColorScale_300'; +import chart_bullet_qualitative_range_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_bullet_qualitative_range_ColorScale_400'; +import chart_bullet_qualitative_range_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_bullet_qualitative_range_ColorScale_500'; +import { ChartComponentThemeDefinition, ChartThemeDefinition } from '../ChartTheme'; + +interface ColorThemeInterface { + COLOR_SCALE: string[]; +} + +/** + * Victory color theme + * + * @private Not intended as public API and subject to change + */ +export const ColorTheme = (props: ColorThemeInterface): ChartThemeDefinition => { + const { COLOR_SCALE } = props; + + return { + area: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: COLOR_SCALE[0] + } + } + }, + axis: { + colorScale: COLOR_SCALE + }, + bar: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: COLOR_SCALE[0] + } + } + }, + boxplot: { + colorScale: COLOR_SCALE, + style: { + q1: { + fill: COLOR_SCALE[0] + }, + q3: { + fill: COLOR_SCALE[0] + } + } + }, + candlestick: { + colorScale: COLOR_SCALE + }, + chart: { + colorScale: COLOR_SCALE + }, + errorbar: { + colorScale: COLOR_SCALE + }, + group: { + colorScale: COLOR_SCALE + }, + legend: { + colorScale: COLOR_SCALE + }, + line: { + colorScale: COLOR_SCALE, + style: { + data: { + stroke: COLOR_SCALE[0] + } + } + }, + pie: { + colorScale: COLOR_SCALE + }, + scatter: { + colorScale: COLOR_SCALE + }, + stack: { + colorScale: COLOR_SCALE + }, + voronoi: { + colorScale: COLOR_SCALE + } + }; +}; + +/** + * Component color theme + * + * @private Not intended as public API and subject to change + */ +export const ColorComponentTheme = (props: ColorThemeInterface): ChartComponentThemeDefinition => { + const { COLOR_SCALE } = props; + + return { + axis: { + axis: { + style: { + grid: { + stroke: chart_axis_grid_stroke_Color.var + }, + ticks: { + stroke: chart_axis_tick_stroke_Color.var + } + } + } + }, + bullet: { + // TBD... + }, + bulletComparativeErrorMeasure: { + bar: { + style: { + data: { + fill: chart_bullet_comparative_measure_error_Fill_Color.var, + stroke: chart_bullet_comparative_measure_error_stroke_Color.var + } + } + } + }, + bulletComparativeMeasure: { + bar: { + height: chart_bullet_Height.value, + style: { + data: { + fill: chart_bullet_comparative_measure_Fill_Color.var, + stroke: chart_bullet_comparative_measure_stroke_Color.var + } + } + } + }, + bulletComparativeWarningMeasure: { + bar: { + height: chart_bullet_Height.value, + style: { + data: { + fill: chart_bullet_comparative_measure_warning_Fill_Color.var, + stroke: chart_bullet_comparative_measure_warning_stroke_Color.var + } + } + } + }, + bulletGroupTitle: { + line: { + style: { + data: { + fill: chart_bullet_group_title_divider_Fill_Color.var, + stroke: chart_bullet_group_title_divider_stroke_Color.var + } + } + } + }, + bulletPrimaryDotMeasure: { + // TBD... + }, + bulletPrimarySegmentedMeasure: { + // TBD... + }, + bulletQualitativeRange: { + group: { + colorScale: [ + chart_bullet_qualitative_range_ColorScale_100.var, + chart_bullet_qualitative_range_ColorScale_200.var, + chart_bullet_qualitative_range_ColorScale_300.var, + chart_bullet_qualitative_range_ColorScale_400.var, + chart_bullet_qualitative_range_ColorScale_500.var + ] + } + }, + bulletPrimaryNegativeMeasure: { + group: { + colorScale: [ + chart_bullet_negative_measure_ColorScale_100.var, + chart_bullet_negative_measure_ColorScale_200.var, + chart_bullet_negative_measure_ColorScale_300.var, + chart_bullet_negative_measure_ColorScale_400.var, + chart_bullet_negative_measure_ColorScale_500.var + ] + } + }, + donut: { + // TBD... + }, + donutThresholdDynamic: { + legend: { + // Merge just the first color of dynamic (blue, green, etc.) with static (grey) for expected colorScale + colorScale: [COLOR_SCALE[0], chart_donut_threshold_second_Color.var, chart_donut_threshold_third_Color.var] + }, + // Merge the threshold colors in case users want to show the unused data + pie: { + colorScale: [ + COLOR_SCALE[0], + chart_donut_threshold_first_Color.var, + chart_donut_threshold_second_Color.var, + chart_donut_threshold_third_Color.var + ] + } + }, + donutThresholdStatic: { + pie: { + colorScale: [ + chart_donut_threshold_first_Color.var, + chart_donut_threshold_second_Color.var, + chart_donut_threshold_third_Color.var + ] + } + }, + donutUtilization: { + legend: { + colorScale: [ + COLOR_SCALE[0], + chart_donut_threshold_first_Color.var, + chart_donut_threshold_second_Color.var, + chart_donut_threshold_third_Color.var + ] + }, + pie: { + colorScale: [COLOR_SCALE[0], chart_donut_threshold_first_Color.var] + } + }, + label: { + // TBD... + }, + threshold: { + // TBD... + } + }; +}; diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/blue-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/blue-theme.ts new file mode 100644 index 00000000000..c07ea2a8170 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/blue-theme.ts @@ -0,0 +1,34 @@ +import chart_theme_blue_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_100'; +import chart_theme_blue_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_200'; +import chart_theme_blue_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_300'; +import chart_theme_blue_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_400'; +import chart_theme_blue_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_blue_ColorScale_100.var, + chart_theme_blue_ColorScale_200.var, + chart_theme_blue_ColorScale_300.var, + chart_theme_blue_ColorScale_400.var, + chart_theme_blue_ColorScale_500.var +]; + +/** + * Blue color theme + * + * @private Not intended as public API and subject to change + */ +export const BlueColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Blue color component theme + * + * @private Not intended as public API and subject to change + */ +export const BlueColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/gray-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/gray-theme.ts new file mode 100644 index 00000000000..10e674296ed --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/gray-theme.ts @@ -0,0 +1,34 @@ +import chart_theme_gray_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_100'; +import chart_theme_gray_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_200'; +import chart_theme_gray_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_300'; +import chart_theme_gray_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_400'; +import chart_theme_gray_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_gray_ColorScale_500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_gray_ColorScale_100.var, + chart_theme_gray_ColorScale_200.var, + chart_theme_gray_ColorScale_300.var, + chart_theme_gray_ColorScale_400.var, + chart_theme_gray_ColorScale_500.var +]; + +/** + * Gray color theme + * + * @private Not intended as public API and subject to change + */ +export const GrayColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Gray component theme + * + * @private Not intended as public API and subject to change + */ +export const GrayColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/green-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/green-theme.ts new file mode 100644 index 00000000000..0ab74406194 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/green-theme.ts @@ -0,0 +1,34 @@ +import chart_theme_green_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_100'; +import chart_theme_green_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_200'; +import chart_theme_green_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_300'; +import chart_theme_green_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_400'; +import chart_theme_green_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_green_ColorScale_500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_green_ColorScale_100.var, + chart_theme_green_ColorScale_200.var, + chart_theme_green_ColorScale_300.var, + chart_theme_green_ColorScale_400.var, + chart_theme_green_ColorScale_500.var +]; + +/** + * Green color theme + * + * @private Not intended as public API and subject to change + */ +export const GreenColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Green color component theme + * + * @private Not intended as public API and subject to change + */ +export const GreenColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/multi-ordered-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/multi-ordered-theme.ts new file mode 100644 index 00000000000..93cf2b092a9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/multi-ordered-theme.ts @@ -0,0 +1,74 @@ +import chart_theme_multi_color_ordered_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_100'; +import chart_theme_multi_color_ordered_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_200'; +import chart_theme_multi_color_ordered_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_300'; +import chart_theme_multi_color_ordered_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_400'; +import chart_theme_multi_color_ordered_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_500'; +import chart_theme_multi_color_ordered_ColorScale_600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_600'; +import chart_theme_multi_color_ordered_ColorScale_700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_700'; +import chart_theme_multi_color_ordered_ColorScale_800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_800'; +import chart_theme_multi_color_ordered_ColorScale_900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_900'; +import chart_theme_multi_color_ordered_ColorScale_1000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1000'; +import chart_theme_multi_color_ordered_ColorScale_1100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1100'; +import chart_theme_multi_color_ordered_ColorScale_1200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1200'; +import chart_theme_multi_color_ordered_ColorScale_1300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1300'; +import chart_theme_multi_color_ordered_ColorScale_1400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1400'; +import chart_theme_multi_color_ordered_ColorScale_1500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1500'; +import chart_theme_multi_color_ordered_ColorScale_1600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1600'; +import chart_theme_multi_color_ordered_ColorScale_1700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1700'; +import chart_theme_multi_color_ordered_ColorScale_1800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1800'; +import chart_theme_multi_color_ordered_ColorScale_1900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1900'; +import chart_theme_multi_color_ordered_ColorScale_2000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2000'; +import chart_theme_multi_color_ordered_ColorScale_2100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2100'; +import chart_theme_multi_color_ordered_ColorScale_2200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2200'; +import chart_theme_multi_color_ordered_ColorScale_2300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2300'; +import chart_theme_multi_color_ordered_ColorScale_2400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2400'; +import chart_theme_multi_color_ordered_ColorScale_2500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// The color order below (minus the purple color family) improves the color contrast in ordered charts; donut, pie, bar, & stack +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_multi_color_ordered_ColorScale_100.var, + chart_theme_multi_color_ordered_ColorScale_200.var, + chart_theme_multi_color_ordered_ColorScale_300.var, + chart_theme_multi_color_ordered_ColorScale_400.var, + chart_theme_multi_color_ordered_ColorScale_500.var, + chart_theme_multi_color_ordered_ColorScale_600.var, + chart_theme_multi_color_ordered_ColorScale_700.var, + chart_theme_multi_color_ordered_ColorScale_800.var, + chart_theme_multi_color_ordered_ColorScale_900.var, + chart_theme_multi_color_ordered_ColorScale_1000.var, + chart_theme_multi_color_ordered_ColorScale_1100.var, + chart_theme_multi_color_ordered_ColorScale_1200.var, + chart_theme_multi_color_ordered_ColorScale_1300.var, + chart_theme_multi_color_ordered_ColorScale_1400.var, + chart_theme_multi_color_ordered_ColorScale_1500.var, + chart_theme_multi_color_ordered_ColorScale_1600.var, + chart_theme_multi_color_ordered_ColorScale_1700.var, + chart_theme_multi_color_ordered_ColorScale_1800.var, + chart_theme_multi_color_ordered_ColorScale_1900.var, + chart_theme_multi_color_ordered_ColorScale_2000.var, + chart_theme_multi_color_ordered_ColorScale_2100.var, + chart_theme_multi_color_ordered_ColorScale_2200.var, + chart_theme_multi_color_ordered_ColorScale_2300.var, + chart_theme_multi_color_ordered_ColorScale_2400.var, + chart_theme_multi_color_ordered_ColorScale_2500.var +]; + +/** + * Multi-color ordered theme + * + * @private Not intended as public API and subject to change + */ +export const MultiColorOrderedTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Multi-color ordered component theme + * + * @private Not intended as public API and subject to change + */ +export const MultiColorOrderedComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/multi-unordered-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/multi-unordered-theme.ts new file mode 100644 index 00000000000..35f0e0541a6 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/multi-unordered-theme.ts @@ -0,0 +1,94 @@ +import chart_theme_multi_color_unordered_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_100'; +import chart_theme_multi_color_unordered_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_200'; +import chart_theme_multi_color_unordered_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_300'; +import chart_theme_multi_color_unordered_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_400'; +import chart_theme_multi_color_unordered_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_500'; +import chart_theme_multi_color_unordered_ColorScale_600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_600'; +import chart_theme_multi_color_unordered_ColorScale_700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_700'; +import chart_theme_multi_color_unordered_ColorScale_800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_800'; +import chart_theme_multi_color_unordered_ColorScale_900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_900'; +import chart_theme_multi_color_unordered_ColorScale_1000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1000'; +import chart_theme_multi_color_unordered_ColorScale_1100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1100'; +import chart_theme_multi_color_unordered_ColorScale_1200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1200'; +import chart_theme_multi_color_unordered_ColorScale_1300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1300'; +import chart_theme_multi_color_unordered_ColorScale_1400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1400'; +import chart_theme_multi_color_unordered_ColorScale_1500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1500'; +import chart_theme_multi_color_unordered_ColorScale_1600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1600'; +import chart_theme_multi_color_unordered_ColorScale_1700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1700'; +import chart_theme_multi_color_unordered_ColorScale_1800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1800'; +import chart_theme_multi_color_unordered_ColorScale_1900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_1900'; +import chart_theme_multi_color_unordered_ColorScale_2000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2000'; +import chart_theme_multi_color_unordered_ColorScale_2100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2100'; +import chart_theme_multi_color_unordered_ColorScale_2200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2200'; +import chart_theme_multi_color_unordered_ColorScale_2300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2300'; +import chart_theme_multi_color_unordered_ColorScale_2400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2400'; +import chart_theme_multi_color_unordered_ColorScale_2500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2500'; +import chart_theme_multi_color_unordered_ColorScale_2600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2600'; +import chart_theme_multi_color_unordered_ColorScale_2700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2700'; +import chart_theme_multi_color_unordered_ColorScale_2800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2800'; +import chart_theme_multi_color_unordered_ColorScale_2900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_2900'; +import chart_theme_multi_color_unordered_ColorScale_3000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3000'; +import chart_theme_multi_color_unordered_ColorScale_3100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3100'; +import chart_theme_multi_color_unordered_ColorScale_3200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3200'; +import chart_theme_multi_color_unordered_ColorScale_3300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3300'; +import chart_theme_multi_color_unordered_ColorScale_3400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3400'; +import chart_theme_multi_color_unordered_ColorScale_3500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_unordered_ColorScale_3500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// The color order below improves the color contrast in unordered charts; area & line +// See https://github.com/patternfly/patternfly-next/issues/1551 +const COLOR_SCALE = [ + chart_theme_multi_color_unordered_ColorScale_100.var, + chart_theme_multi_color_unordered_ColorScale_200.var, + chart_theme_multi_color_unordered_ColorScale_300.var, + chart_theme_multi_color_unordered_ColorScale_400.var, + chart_theme_multi_color_unordered_ColorScale_500.var, + chart_theme_multi_color_unordered_ColorScale_600.var, + chart_theme_multi_color_unordered_ColorScale_700.var, + chart_theme_multi_color_unordered_ColorScale_800.var, + chart_theme_multi_color_unordered_ColorScale_900.var, + chart_theme_multi_color_unordered_ColorScale_1000.var, + chart_theme_multi_color_unordered_ColorScale_1100.var, + chart_theme_multi_color_unordered_ColorScale_1200.var, + chart_theme_multi_color_unordered_ColorScale_1300.var, + chart_theme_multi_color_unordered_ColorScale_1400.var, + chart_theme_multi_color_unordered_ColorScale_1500.var, + chart_theme_multi_color_unordered_ColorScale_1600.var, + chart_theme_multi_color_unordered_ColorScale_1700.var, + chart_theme_multi_color_unordered_ColorScale_1800.var, + chart_theme_multi_color_unordered_ColorScale_1900.var, + chart_theme_multi_color_unordered_ColorScale_2000.var, + chart_theme_multi_color_unordered_ColorScale_2100.var, + chart_theme_multi_color_unordered_ColorScale_2200.var, + chart_theme_multi_color_unordered_ColorScale_2300.var, + chart_theme_multi_color_unordered_ColorScale_2400.var, + chart_theme_multi_color_unordered_ColorScale_2500.var, + chart_theme_multi_color_unordered_ColorScale_2600.var, + chart_theme_multi_color_unordered_ColorScale_2700.var, + chart_theme_multi_color_unordered_ColorScale_2800.var, + chart_theme_multi_color_unordered_ColorScale_2900.var, + chart_theme_multi_color_unordered_ColorScale_3000.var, + chart_theme_multi_color_unordered_ColorScale_3100.var, + chart_theme_multi_color_unordered_ColorScale_3200.var, + chart_theme_multi_color_unordered_ColorScale_3300.var, + chart_theme_multi_color_unordered_ColorScale_3400.var, + chart_theme_multi_color_unordered_ColorScale_3500.var +]; + +/** + * Multi-color unordered theme + * + * @private Not intended as public API and subject to change + */ +export const MultiColorUnorderedTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Multi-color unordered component theme + * + * @private Not intended as public API and subject to change + */ +export const MultiColorUnorderedComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/orange-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/orange-theme.ts new file mode 100644 index 00000000000..65f64c2a46f --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/orange-theme.ts @@ -0,0 +1,34 @@ +import chart_theme_orange_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_100'; +import chart_theme_orange_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_200'; +import chart_theme_orange_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_300'; +import chart_theme_orange_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_400'; +import chart_theme_orange_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_orange_ColorScale_100.var, + chart_theme_orange_ColorScale_200.var, + chart_theme_orange_ColorScale_300.var, + chart_theme_orange_ColorScale_400.var, + chart_theme_orange_ColorScale_500.var +]; + +/** + * Orange color theme + * + * @private Not intended as public API and subject to change + */ +export const OrangeColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Orange color component theme + * + * @private Not intended as public API and subject to change + */ +export const OrangeColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/purple-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/purple-theme.ts new file mode 100644 index 00000000000..98766913a40 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/purple-theme.ts @@ -0,0 +1,34 @@ +import chart_theme_purple_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_100'; +import chart_theme_purple_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_200'; +import chart_theme_purple_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_300'; +import chart_theme_purple_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_400'; +import chart_theme_purple_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_purple_ColorScale_500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_purple_ColorScale_100.var, + chart_theme_purple_ColorScale_200.var, + chart_theme_purple_ColorScale_300.var, + chart_theme_purple_ColorScale_400.var, + chart_theme_purple_ColorScale_500.var +]; + +/** + * Purple ordered theme + * + * @private Not intended as public API and subject to change + */ +export const PurpleColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Purple color component theme + * + * @private Not intended as public API and subject to change + */ +export const PurpleColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/skeleton-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/skeleton-theme.ts new file mode 100644 index 00000000000..37af537de4a --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/skeleton-theme.ts @@ -0,0 +1,34 @@ +import { ColorTheme, ColorComponentTheme } from '../skeleton-theme'; +import chart_skeleton_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_100'; +import chart_skeleton_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_200'; +import chart_skeleton_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_300'; +import chart_skeleton_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_400'; +import chart_skeleton_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_skeleton_ColorScale_500'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_skeleton_ColorScale_100.var, + chart_skeleton_ColorScale_200.var, + chart_skeleton_ColorScale_300.var, + chart_skeleton_ColorScale_400.var, + chart_skeleton_ColorScale_500.var +]; + +/** + * Skeleton color theme + * + * @private Not intended as public API and subject to change + */ +export const SkeletonColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Skeleton color theme + * + * @private Not intended as public API and subject to change + */ +export const SkeletonColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/teal-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/teal-theme.ts new file mode 100644 index 00000000000..99d7df686f9 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/teal-theme.ts @@ -0,0 +1,34 @@ +import chart_theme_teal_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_100'; +import chart_theme_teal_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_200'; +import chart_theme_teal_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_300'; +import chart_theme_teal_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_400'; +import chart_theme_teal_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_teal_ColorScale_500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_teal_ColorScale_100.var, + chart_theme_teal_ColorScale_200.var, + chart_theme_teal_ColorScale_300.var, + chart_theme_teal_ColorScale_400.var, + chart_theme_teal_ColorScale_500.var +]; + +/** + * Teal color theme + * + * @private Not intended as public API and subject to change + */ +export const TealColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Teal color component theme + * + * @private Not intended as public API and subject to change + */ +export const TealColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/colors/yellow-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/yellow-theme.ts new file mode 100644 index 00000000000..87879349956 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/colors/yellow-theme.ts @@ -0,0 +1,34 @@ +import chart_theme_yellow_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_100'; +import chart_theme_yellow_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_200'; +import chart_theme_yellow_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_300'; +import chart_theme_yellow_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_400'; +import chart_theme_yellow_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_yellow_ColorScale_500'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + chart_theme_yellow_ColorScale_100.var, + chart_theme_yellow_ColorScale_200.var, + chart_theme_yellow_ColorScale_300.var, + chart_theme_yellow_ColorScale_400.var, + chart_theme_yellow_ColorScale_500.var +]; + +/** + * Yellow color theme + * + * @private Not intended as public API and subject to change + */ +export const YellowColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Yellow color component theme + * + * @private Not intended as public API and subject to change + */ +export const YellowColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/victory/components/ChartTheme/themes/skeleton-theme.ts b/packages/react-charts/src/victory/components/ChartTheme/themes/skeleton-theme.ts new file mode 100644 index 00000000000..682f2325dcd --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTheme/themes/skeleton-theme.ts @@ -0,0 +1,312 @@ +import { ChartComponentThemeDefinition, ChartThemeDefinition } from '../ChartTheme'; + +interface ColorThemeInterface { + COLOR_SCALE: string[]; +} + +// Labels +const LABEL_PROPS = { + fill: 'transparent', + stroke: 'transparent' +}; + +const LABEL_CENTERED_PROPS = { + ...LABEL_PROPS +}; + +/** + * Victory color theme + * + * @private Not intended as public API and subject to change + */ +export const ColorTheme = (props: ColorThemeInterface): ChartThemeDefinition => { + const { COLOR_SCALE } = props; + + return { + area: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: COLOR_SCALE[0] + }, + labels: LABEL_CENTERED_PROPS + } + }, + axis: { + colorScale: COLOR_SCALE, + style: { + axis: { + fill: 'transparent', + stroke: COLOR_SCALE[0] + }, + axisLabel: { + ...LABEL_CENTERED_PROPS, + fill: COLOR_SCALE[0], + stroke: 'transparent' + }, + grid: { + fill: 'transparent', + stroke: 'transparent' + }, + ticks: { + fill: 'transparent', + stroke: COLOR_SCALE[0] + }, + tickLabels: { + ...LABEL_PROPS, + fill: 'transparent' + } + } + }, + bar: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: COLOR_SCALE[0], + stroke: COLOR_SCALE[0] + }, + labels: LABEL_PROPS + } + }, + boxplot: { + colorScale: COLOR_SCALE, + style: { + max: { + stroke: COLOR_SCALE[0] + }, + maxLabels: LABEL_PROPS, + median: { + stroke: COLOR_SCALE[0] + }, + medianLabels: LABEL_PROPS, + min: { + stroke: COLOR_SCALE[0] + }, + minLabels: LABEL_PROPS, + q1: { + fill: COLOR_SCALE[0] + }, + q1Labels: LABEL_PROPS, + q3: { + fill: COLOR_SCALE[0] + }, + q3Labels: LABEL_PROPS + } + }, + candlestick: { + colorScale: COLOR_SCALE, + style: { + data: { + stroke: COLOR_SCALE[0] + }, + labels: LABEL_CENTERED_PROPS + } + }, + chart: { + colorScale: COLOR_SCALE + }, + errorbar: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: 'transparent', + stroke: COLOR_SCALE[0] + }, + labels: LABEL_CENTERED_PROPS + } + }, + group: { + colorScale: COLOR_SCALE + }, + legend: { + colorScale: COLOR_SCALE, + style: { + labels: LABEL_PROPS, + title: { + ...LABEL_PROPS + }, + data: { + stroke: 'transparent', + strokeWidth: 0 + } + } + }, + line: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: 'transparent', + stroke: COLOR_SCALE[0] + }, + labels: LABEL_CENTERED_PROPS + } + }, + pie: { + colorScale: COLOR_SCALE, + style: { + data: { + stroke: 'transparent' + }, + labels: { + ...LABEL_PROPS + } + } + }, + scatter: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: COLOR_SCALE[0], + stroke: 'transparent' + }, + labels: LABEL_CENTERED_PROPS + } + }, + stack: { + colorScale: COLOR_SCALE + }, + tooltip: { + flyoutStyle: { + fill: 'transparent', // background + stroke: 'transparent' // border + }, + style: { + fill: 'transparent' // text + } + }, + voronoi: { + colorScale: COLOR_SCALE, + style: { + data: { + fill: COLOR_SCALE[0], + stroke: COLOR_SCALE[0] + }, + labels: { + ...LABEL_CENTERED_PROPS, + fill: 'transparent' // text + }, + // Note: These properties override tooltip + flyout: { + fill: 'transparent', // background + stroke: 'transparent' // border + } + } + } + }; +}; + +/** + * Component color theme + * + * @private Not intended as public API and subject to change + */ +export const ColorComponentTheme = (props: ColorThemeInterface): ChartComponentThemeDefinition => { + const { COLOR_SCALE } = props; + + return { + axis: { + axis: { + style: { + grid: { + stroke: COLOR_SCALE[0] + }, + ticks: { + stroke: COLOR_SCALE[0] + } + } + } + }, + bullet: { + // TBD... + }, + bulletComparativeErrorMeasure: { + bar: { + style: { + data: { + fill: COLOR_SCALE[0], + stroke: COLOR_SCALE[0] + } + } + } + }, + bulletComparativeMeasure: { + bar: { + style: { + data: { + fill: COLOR_SCALE[0], + stroke: COLOR_SCALE[0] + } + } + } + }, + bulletComparativeWarningMeasure: { + bar: { + style: { + data: { + fill: COLOR_SCALE[0], + stroke: COLOR_SCALE[0] + } + } + } + }, + bulletGroupTitle: { + line: { + style: { + data: { + fill: COLOR_SCALE[0], + stroke: COLOR_SCALE[0] + } + } + } + }, + bulletPrimaryDotMeasure: { + // TBD... + }, + bulletPrimaryNegativeMeasure: { + group: { + colorScale: COLOR_SCALE + } + }, + bulletPrimarySegmentedMeasure: { + // TBD... + }, + bulletQualitativeRange: { + group: { + colorScale: COLOR_SCALE + } + }, + donut: { + // TBD... + }, + donutThresholdDynamic: { + legend: { + colorScale: COLOR_SCALE + }, + pie: { + colorScale: COLOR_SCALE + } + }, + donutThresholdStatic: { + pie: { + colorScale: COLOR_SCALE + } + }, + donutUtilization: { + legend: { + colorScale: COLOR_SCALE + }, + pie: { + colorScale: COLOR_SCALE + } + }, + label: { + backgroundStyle: { + fill: COLOR_SCALE[0] + }, + style: LABEL_CENTERED_PROPS + }, + threshold: { + // TBD... + } + }; +}; diff --git a/packages/react-charts/src/victory/components/ChartThreshold/ChartThreshold.test.tsx b/packages/react-charts/src/victory/components/ChartThreshold/ChartThreshold.test.tsx new file mode 100644 index 00000000000..314240ba9e0 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartThreshold/ChartThreshold.test.tsx @@ -0,0 +1,28 @@ +import { render } from '@testing-library/react'; +import { Chart } from '../Chart/Chart'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartThreshold } from './ChartThreshold'; + +Object.values([true, false]).forEach(() => { + test('ChartThreshold', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders component data', () => { + const data = [ + { name: 'Birds Threshold', x: 0, y: 2 }, + { name: 'Birds Threshold', x: 2, y: 2 }, + { name: 'Birds Threshold', x: 2, y: 3 }, + { name: 'Birds Threshold', x: 5, y: 3 } + ]; + const { asFragment } = render( + + + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartThreshold/ChartThreshold.tsx b/packages/react-charts/src/victory/components/ChartThreshold/ChartThreshold.tsx similarity index 94% rename from packages/react-charts/src/components/ChartThreshold/ChartThreshold.tsx rename to packages/react-charts/src/victory/components/ChartThreshold/ChartThreshold.tsx index 1f0d7243923..a0579d7d706 100644 --- a/packages/react-charts/src/components/ChartThreshold/ChartThreshold.tsx +++ b/packages/react-charts/src/victory/components/ChartThreshold/ChartThreshold.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import cloneDeep from 'lodash/cloneDeep'; import { @@ -21,13 +20,14 @@ import { VictoryStyleInterface } from 'victory-core'; import { VictoryLine, VictoryLineProps, VictoryLineTTargetType } from 'victory-line'; -import { ChartLine } from '../ChartLine'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getThresholdTheme } from '../ChartUtils'; +import { ChartLine } from '../ChartLine/ChartLine'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getThresholdTheme } from '../ChartUtils/chart-theme-types'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-line/src/index.d.ts + * CharThreshold renders a dataset as a threshold chart. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-line/src/victory-line.tsx */ export interface ChartThresholdProps extends VictoryLineProps { /** @@ -125,7 +125,7 @@ export interface ChartThresholdProps extends VictoryLineProps { * Since ChartLine only renders a single element, the eventKey property is not used. * The eventHandlers object should be given as an object whose keys are standard * event names (i.e. onClick) and whose values are event callbacks. The return value - * of an event handler is used to modify elemnts. The return value should be given + * of an event handler is used to modify elements. The return value should be given * as an object or an array of objects with optional target and eventKey keys, * and a mutation key whose value is a function. The target and eventKey keys * will default to those corresponding to the element the event handler was attached to. @@ -217,7 +217,7 @@ export interface ChartThresholdProps extends VictoryLineProps { * domain of a chart is static, while the minimum value depends on data or other variable information. If the domain * prop is set in addition to maximumDomain, domain will be used. * - * note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the maxDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -232,7 +232,7 @@ export interface ChartThresholdProps extends VictoryLineProps { * domain of a chart is static, while the maximum value depends on data or other variable information. If the domain * prop is set in addition to minimumDomain, domain will be used. * - * note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the + * Note: The x value supplied to the minDomain prop refers to the independent variable, and the y value refers to the * dependent variable. This may cause confusion in horizontal charts, as the independent variable will corresponds to * the y axis. * @@ -268,6 +268,7 @@ export interface ChartThresholdProps extends VictoryLineProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -311,6 +312,7 @@ export interface ChartThresholdProps extends VictoryLineProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ sharedEvents?: { events: any[]; getEventState: Function }; @@ -322,7 +324,7 @@ export interface ChartThresholdProps extends VictoryLineProps { * specified for "x" and/or "y". When this prop is false (or false for a given dimension), padding will be applied * without regard to quadrant. If this prop is not specified, domainPadding will be coerced to existing quadrants. * - * note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y + * Note: The x value supplied to the singleQuadrantDomainPadding prop refers to the independent variable, and the y * value refers to the dependent variable. This may cause confusion in horizontal charts, as the independent variable * will corresponds to the y axis. * @@ -337,7 +339,7 @@ export interface ChartThresholdProps extends VictoryLineProps { * is given directly to the lodash sortBy function to be executed on the * final dataset. */ - sortKey?: string | string[] | Function; + sortKey?: DataGetterPropType; /** * The sortOrder prop specifies whether sorted data should be returned in 'ascending' or 'descending' order. * @@ -378,14 +380,6 @@ export interface ChartThresholdProps extends VictoryLineProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The width props specifies the width of the svg viewBox of the chart container * This value should be given as a number of pixels @@ -431,10 +425,9 @@ export interface ChartThresholdProps extends VictoryLineProps { export const ChartThreshold: React.FunctionComponent = ({ style = {}, themeColor, - themeVariant, // destructure last - theme = getThresholdTheme(themeColor, themeVariant), + theme = getThresholdTheme(themeColor), ...rest }: ChartThresholdProps) => { // Returned style prop takes precedence over default theme @@ -442,13 +435,13 @@ export const ChartThreshold: React.FunctionComponent = ({ if (style && style.data && style.data.strokeDasharray) { return style.data.strokeDasharray; } - return getThresholdTheme(themeColor, themeVariant).line.style.data.strokeDasharray; + return getThresholdTheme(themeColor).line.style.data.strokeDasharray; }; const getStrokeWidth = () => { if (style && style.data && style.data.strokeWidth) { return style.data.strokeWidth; } - return getThresholdTheme(themeColor, themeVariant).line.style.data.strokeWidth; + return getThresholdTheme(themeColor).line.style.data.strokeWidth; }; // Clone style and apply strokeDasharray prop @@ -462,7 +455,7 @@ export const ChartThreshold: React.FunctionComponent = ({ strokeWidth: getStrokeWidth() }; } - return ; + return ; }; ChartThreshold.displayName = 'ChartThreshold'; diff --git a/packages/react-charts/src/victory/components/ChartThreshold/__snapshots__/ChartThreshold.test.tsx.snap b/packages/react-charts/src/victory/components/ChartThreshold/__snapshots__/ChartThreshold.test.tsx.snap new file mode 100644 index 00000000000..39d12222996 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartThreshold/__snapshots__/ChartThreshold.test.tsx.snap @@ -0,0 +1,528 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartThreshold 1`] = ` + +
    + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`ChartThreshold 2`] = ` + +
    + + + + + + + + + + +
    + +
    +
    +
    +`; + +exports[`renders component data 1`] = ` + +
    + + + + + + + + + + + + + + + + + + 1.0 + + + + + + + + 2.0 + + + + + + + + 3.0 + + + + + + + + 4.0 + + + + + + + + 5.0 + + + + + + + + + + + 0.5 + + + + + + + + 1.0 + + + + + + + + 1.5 + + + + + + + + 2.0 + + + + + + + + 2.5 + + + + + + + + 3.0 + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartThreshold/examples/ChartThreshold.md b/packages/react-charts/src/victory/components/ChartThreshold/examples/ChartThreshold.md new file mode 100644 index 00000000000..179f19f9ec1 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartThreshold/examples/ChartThreshold.md @@ -0,0 +1,60 @@ +--- +id: Threshold chart +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartAxis', + 'ChartGroup', + 'ChartThreshold', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { createRef } from 'react'; +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartLegend, + ChartThreshold, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; +import { useEffect, useRef, useState } from 'react'; + + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, + along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Multi-color (unordered) with responsive container +```ts file = "ChartThresholdMultiColorOrdered.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + + - For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) + - For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) + - For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) + - For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) + - For `ChartLegend` props, see [VictoryLegend](https://formidable.com/open-source/victory/docs/victory-legend) + - For `ChartThreshold` props, see [VictoryLine](https://formidable.com/open-source/victory/docs/victory-line) + - For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/ChartThreshold/examples/ChartThresholdMultiColorOrdered.tsx b/packages/react-charts/src/victory/components/ChartThreshold/examples/ChartThresholdMultiColorOrdered.tsx new file mode 100644 index 00000000000..1d51e58eccf --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartThreshold/examples/ChartThresholdMultiColorOrdered.tsx @@ -0,0 +1,136 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartLegend, + ChartGroup, + ChartThreshold, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; +import { useEffect, useRef, useState } from 'react'; + +interface PetData { + name?: string; + symbol?: { fill: string; type: string }; + x?: number; + y?: number; +} + +export const ChartThresholdMultiColorOrdered: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + const itemsPerRow = width > 650 ? 4 : 2; + + const data1: PetData[] = [ + { name: 'Cats' }, + { name: 'Birds' }, + { + name: 'Cats Threshold', + symbol: { fill: chart_color_blue_300.var, type: 'threshold' } + }, + { + name: 'Birds Threshold', + symbol: { fill: chart_color_orange_300.var, type: 'threshold' } + } + ]; + + const data2: PetData[] = [ + { name: 'Cats', x: 1, y: 3 }, + { name: 'Cats', x: 2, y: 4 }, + { name: 'Cats', x: 3, y: 8 }, + { name: 'Cats', x: 4, y: 6 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: 1, y: 2 }, + { name: 'Birds', x: 2, y: 3 }, + { name: 'Birds', x: 3, y: 4 }, + { name: 'Birds', x: 4, y: 5 }, + { name: 'Birds', x: 5, y: 6 } + ]; + + const data4: PetData[] = [ + { name: 'Cats Threshold', x: 0, y: 4 }, + { name: 'Cats Threshold', x: 3, y: 4 }, + { name: 'Cats Threshold', x: 3, y: 6 }, + { name: 'Cats Threshold', x: 5, y: 6 } + ]; + + const data5: PetData[] = [ + { name: 'Birds Threshold', x: 0, y: 2 }, + { name: 'Birds Threshold', x: 2, y: 2 }, + { name: 'Birds Threshold', x: 2, y: 3 }, + { name: 'Birds Threshold', x: 5, y: 3 } + ]; + + return ( +
    +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendPosition="bottom-left" + legendComponent={} + height={250} + padding={{ + bottom: 100, // Adjusted to accomodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + name="chart1" + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + + + + + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/ChartTooltip.test.tsx b/packages/react-charts/src/victory/components/ChartTooltip/ChartTooltip.test.tsx new file mode 100644 index 00000000000..136b898918c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/ChartTooltip.test.tsx @@ -0,0 +1,41 @@ +import { render } from '@testing-library/react'; +import { ChartArea } from '../ChartArea/ChartArea'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartVoronoiContainer } from '../ChartVoronoiContainer/ChartVoronoiContainer'; +import { ChartTooltip } from './ChartTooltip'; + +Object.values([true, false]).forEach(() => { + test('ChartTooltip', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('allows tooltip via container component', () => { + const { asFragment } = render( + 'y: ' + point.y} />} + height={200} + width={200} + > + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartTooltip/ChartTooltip.tsx b/packages/react-charts/src/victory/components/ChartTooltip/ChartTooltip.tsx similarity index 90% rename from packages/react-charts/src/components/ChartTooltip/ChartTooltip.tsx rename to packages/react-charts/src/victory/components/ChartTooltip/ChartTooltip.tsx index 495ac6a297a..233c7e93b49 100644 --- a/packages/react-charts/src/components/ChartTooltip/ChartTooltip.tsx +++ b/packages/react-charts/src/victory/components/ChartTooltip/ChartTooltip.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { NumberOrCallback, @@ -9,13 +9,20 @@ import { VictoryStyleObject } from 'victory-core'; import { VictoryTooltip, VictoryTooltipProps } from 'victory-tooltip'; -import { ChartLabel } from '../ChartLabel'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { getTheme } from '../ChartUtils'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-tooltip/src/index.d.ts + * ChartTooltip renders a tooltip component with a set of default events. When ChartTooltip is used as a label component + * for any Victory based component that renders data, it will attach events to rendered data components that will + * activate the tooltip when hovered or focused. ChartTooltipTooltip renders text as well as a configurable Flyout + * container. + * + * Note: When providing tooltips for ChartLine or ChartArea, it is necessary to use ChartVoronoiContainer, as these + * components only render a single element for the entire dataset. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-tooltip/src/index.d.ts */ export interface ChartTooltipProps extends VictoryTooltipProps { /** @@ -29,7 +36,7 @@ export interface ChartTooltipProps extends VictoryTooltipProps { /** * The angle prop specifies the angle to rotate the tooltip around its origin point. */ - angle?: string | number; + angle?: number; /** * The center prop determines the position of the center of the tooltip flyout. This prop should be given as an object * that describes the desired x and y svg coordinates of the center of the tooltip. This prop is useful for @@ -140,6 +147,7 @@ export interface ChartTooltipProps extends VictoryTooltipProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ height?: number; @@ -217,7 +225,7 @@ export interface ChartTooltipProps extends VictoryTooltipProps { * * @propType number | string | Function | string[] | number[] */ - text?: StringOrNumberOrCallback | string[] | number[]; + text?: string[] | StringOrNumberOrCallback; /** * The theme prop specifies a theme to use for determining styles and layout properties for a component. Any styles or * props defined in theme may be overwritten by props specified on the component instance. @@ -233,14 +241,6 @@ export interface ChartTooltipProps extends VictoryTooltipProps { * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * This prop refers to the width of the svg that ChartTooltip is rendered within. This prop is passed from parents * of ChartTooltip, and should not be set manually. In versions before ^33.0.0 this prop referred to the width of the @@ -248,6 +248,7 @@ export interface ChartTooltipProps extends VictoryTooltipProps { * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ width?: number; @@ -266,13 +267,12 @@ export const ChartTooltip: React.FunctionComponent = ({ labelComponent = , // Note that Victory provides its own label component here labelTextAnchor, themeColor, - themeVariant, // destructure last - theme = getTheme(themeColor, themeVariant), + theme = getTheme(themeColor), ...rest }: ChartTooltipProps) => { - const chartLabelComponent = React.cloneElement(labelComponent, { + const chartLabelComponent = cloneElement(labelComponent, { textAnchor: labelTextAnchor, theme, ...labelComponent.props diff --git a/packages/react-charts/src/victory/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap b/packages/react-charts/src/victory/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap new file mode 100644 index 00000000000..6fa3536b5b7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ChartTooltip 1`] = ``; + +exports[`ChartTooltip 2`] = ``; + +exports[`allows tooltip via container component 1`] = ` + +
    + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltip.md b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltip.md new file mode 100644 index 00000000000..41561f60db8 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltip.md @@ -0,0 +1,142 @@ +--- +id: Tooltips +section: components +subsection: charts +propComponents: ['ChartTooltip'] +hideDarkMode: true +--- + +import { useRef, useState, useEffect } from 'react'; +import { + Chart, + ChartArea, + ChartAxis, + ChartBar, + ChartContainer, + ChartCursorFlyout, + ChartCursorTooltip, + ChartDonut, + ChartDonutThreshold, + ChartDonutUtilization, + ChartGroup, + ChartLabel, + ChartLegend, + ChartLegendTooltip, + ChartLegendTooltipContent, + ChartLegendTooltipLabel, + ChartLine, + ChartPie, + ChartPoint, + ChartStack, + ChartThemeColor, + ChartTooltip, + ChartVoronoiContainer, + createContainer, + getCustomTheme +} from '@patternfly/react-charts/victory'; + + + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Voronoi container + +This demonstrates how to use a voronoi container to display tooltips. + +```ts file = "ChartTooltipVoronoi.tsx" + +``` + +### Combined cursor and voronoi containers + +This demonstrates how to combine cursor and voronoi containers to display tooltips along with a vertical cursor. + +```ts file = "ChartTooltipCombinedCursorVoronoi.tsx" + +``` + +### Embedded legend + +This demonstrates how to embed a legend within a tooltip. Combining cursor and voronoi containers is required to display tooltips with a vertical cursor. + +```ts file = "ChartTooltipEmbeddedLegend.tsx" + +``` + +### Embedded HTML + +This demonstrates how to embed HTML within a tooltip. Combining cursor and voronoi containers is required to display tooltips with a vertical cursor. + +```ts file = "ChartTooltipEmbeddedHtml.tsx" + +``` + +### Embedded legend with custom font size + +This demonstrates how to embed a legend within a tooltip, but with a custom font size. Combining cursor and voronoi containers is required to display tooltips with a vertical cursor. + +```ts file = "ChartTooltipEmbeddedCustomFontSize.tsx" + +``` + +### Data label + +This demonstrates an alternate way of applying tooltips using data labels. + +```ts file = "ChartTooltipDataLabel.tsx" + +``` + +### Fixed tooltip +This demonstrates how to adjust the tooltip position and label radius +```ts file = "ChartTooltipFixed.tsx" + +``` + +### Legend + +This demonstrates an approach for applying tooltips to a legend using a custom legend label component. + +```ts file = "ChartTooltipLegend.tsx" + +``` + +### Left aligned + +This demonstrates how to customize tooltip label alignment using theme properties. + +```ts file = "ChartTooltipLeftAligned.tsx" + +``` + +### CSS overflow + +This demonstrates an alternate way of applying tooltips using CSS overflow instead of constrainToVisibleArea. + +```ts file = "ChartTooltipCssOverflow.tsx" + +``` + +### Wrapped chart + +This demonstrates an alternate way of applying tooltips by wrapping charts with the Tooltip component. + +```ts file = "ChartTooltipWrappedChart.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `ChartTooltip` props, see [VictoryTooltip](https://formidable.com/open-source/victory/docs/victory-tooltip) diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipCombinedCursorVoronoi.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipCombinedCursorVoronoi.tsx new file mode 100644 index 00000000000..763610b524d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipCombinedCursorVoronoi.tsx @@ -0,0 +1,102 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLine, + ChartThemeColor, + createContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + symbol?: { type: string }; + x?: string; + y?: number; +} + +export const ChartTooltipCombinedCursorVoronoi: React.FunctionComponent = () => { + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart2" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.orange} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipCssOverflow.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipCssOverflow.tsx new file mode 100644 index 00000000000..3933f0deb34 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipCssOverflow.tsx @@ -0,0 +1,58 @@ +import { + ChartArea, + ChartGroup, + ChartLabel, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { useEffect } from 'react'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartTooltipCssOverflow: React.FunctionComponent = () => { + // Workaround for documentation-framework issue https://github.com/patternfly/patternfly-react/issues/11455 + useEffect(() => { + const sheet = (() => { + const style = document.createElement('style'); + document.head.appendChild(style); + return style.sheet; + })(); + + sheet.insertRule( + '.ws-react-charts-tooltip-overflow { margin-left: 50px; margin-top: 50px; height: 135px; }', + sheet.cssRules.length + ); + sheet.insertRule('.ws-react-charts-tooltip-overflow svg { overflow: visible; }', sheet.cssRules.length); + }, []); + + const data: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + return ( +
    +
    + `${datum.name}: ${datum.y}`} />} + height={100} + maxDomain={{ y: 9 }} + name="chart9" + padding={0} + themeColor={ChartThemeColor.green} + width={400} + > + + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipDataLabel.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipDataLabel.tsx new file mode 100644 index 00000000000..f834f852f83 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipDataLabel.tsx @@ -0,0 +1,77 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartStack, + ChartThemeColor, + ChartTooltip +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number; + label?: string; +} + +export const ChartTooltipDataLabel: React.FunctionComponent = () => { + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1, label: 'Cats: 1' }, + { name: 'Cats', x: '2016', y: 2, label: 'Cats: 2' }, + { name: 'Cats', x: '2017', y: 5, label: 'Cats: 5' }, + { name: 'Cats', x: '2018', y: 3, label: 'Cats: 3' } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2, label: 'Dogs: 2' }, + { name: 'Dogs', x: '2016', y: 1, label: 'Dogs: 1' }, + { name: 'Dogs', x: '2017', y: 7, label: 'Dogs: 7' }, + { name: 'Dogs', x: '2018', y: 4, label: 'Dogs: 4' } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4, label: 'Birds: 4' }, + { name: 'Birds', x: '2016', y: 4, label: 'Birds: 4' }, + { name: 'Birds', x: '2017', y: 9, label: 'Birds: 9' }, + { name: 'Birds', x: '2018', y: 7, label: 'Birds: 7' } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3, label: 'Mice: 3' }, + { name: 'Mice', x: '2016', y: 3, label: 'Mice: 3' }, + { name: 'Mice', x: '2017', y: 8, label: 'Mice: 8' }, + { name: 'Mice', x: '2018', y: 5, label: 'Mice: 5' } + ]; + + return ( +
    + + + + + } /> + } /> + } /> + } /> + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedCustomFontSize.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedCustomFontSize.tsx new file mode 100644 index 00000000000..35e09573ed4 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedCustomFontSize.tsx @@ -0,0 +1,121 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLegendTooltip, + ChartLegend, + ChartLine, + ChartLegendTooltipContent, + ChartLegendTooltipLabel, + ChartThemeColor, + createContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + childName?: string; + name?: string; + symbol?: { type: string }; + x?: string; + y?: number | null; +} + +export const ChartTooltipEmbeddedLegendFont: React.FunctionComponent = () => { + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData: PetData[] = [ + { childName: 'cats', name: 'Cats' }, + { childName: 'dogs', name: 'Dogs', symbol: { type: 'dash' } }, + { childName: 'birds', name: 'Birds' }, + { childName: 'mice', name: 'Mice' } + ]; + + const legend = ; + const legendTooltipLabel = ; + const legendTooltipContent = ( + + ); + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: null }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.y !== null ? datum.y : 'no data'}`} + labelComponent={ + datum.x} + /> + } + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart5" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.yellow} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedHtml.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedHtml.tsx new file mode 100644 index 00000000000..d339f2fc868 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedHtml.tsx @@ -0,0 +1,149 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartCursorTooltip, + ChartGroup, + ChartPoint, + ChartThemeColor, + createContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number | null; +} + +export const ChartTooltipEmbeddedHtml: React.FunctionComponent = () => { + const baseStyles = { + color: '#f0f0f0', + fontFamily: + '"Red Hat Text", "RedHatText", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans JP", "Noto Sans KR", "Noto Sans Malayalam", "Noto Sans SC", "Noto Sans TC", "Noto Sans Thai", Helvetica, Arial, sans-serif', + fontSize: '14px' + }; + + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 }, + { name: 'Cats', x: '2019', y: null } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 3 }, + { name: 'Dogs', x: '2017', y: 4 }, + { name: 'Dogs', x: '2018', y: 5 }, + { name: 'Dogs', x: '2019', y: 6 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 1 }, + { name: 'Birds', x: '2016', y: 2 }, + { name: 'Birds', x: '2017', y: 3 }, + { name: 'Birds', x: '2018', y: 2 }, + { name: 'Birds', x: '2019', y: 4 } + ]; + + // Custom HTML component to create a legend layout + const HtmlLegendContent = ({ datum, legendData, text, theme, title, x, y, ..._rest }) => ( + + + + + + + + + + {text.map((val, index) => ( + + + + + + ))} + +
    + {title(datum)} +
    + + + + { + + } + + + + {legendData[index].name}{val}
    +
    +
    + ); + + return ( +
    + `${datum.y !== null ? datum.y : 'no data'}`} + labelComponent={ + width > center.x + flyoutWidth + 10 ? offset : -offset}} + // flyoutComponent={} + flyoutHeight={110} + flyoutWidth={({ datum }) => (datum.y === null ? 160 : 125)} + labelComponent={ datum.x} />} + /> + } + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom-left" + height={225} + name="chart4" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.multiUnordered} + width={650} + > + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedLegend.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedLegend.tsx new file mode 100644 index 00000000000..fc4fc6c1dd3 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipEmbeddedLegend.tsx @@ -0,0 +1,106 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLegendTooltip, + ChartLine, + ChartThemeColor, + createContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + childName?: string; + name?: string; + symbol?: { type: string }; + x?: string; + y?: number; +} + +export const ChartTooltipEmbeddedLegend: React.FunctionComponent = () => { + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData: PetData[] = [ + { childName: 'cats', name: 'Cats' }, + { childName: 'dogs', name: 'Dogs', symbol: { type: 'dash' } }, + { childName: 'birds', name: 'Birds' }, + { childName: 'mice', name: 'Mice' } + ]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: null }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.y !== null ? datum.y : 'no data'}`} + labelComponent={ datum.x} />} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + } + legendData={legendData} + legendPosition="bottom" + height={275} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart3" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.green} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipFixed.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipFixed.tsx new file mode 100644 index 00000000000..92a3552644f --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipFixed.tsx @@ -0,0 +1,34 @@ +import { ChartDonut, ChartThemeColor, ChartTooltip } from '@patternfly/react-charts/victory'; + +interface PetData { + x: string; + y: number; +} + +export const ChartTooltipFixed: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + return ( +
    + } + labelRadius={46} + labels={({ datum }) => `${datum.x}: ${datum.y}%`} + name="chart5" + subTitle="Pets" + title="100" + themeColor={ChartThemeColor.teal} + width={150} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipLeftAligned.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipLeftAligned.tsx new file mode 100644 index 00000000000..cf2b6adbf03 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipLeftAligned.tsx @@ -0,0 +1,114 @@ +import { + Chart, + ChartAxis, + ChartGroup, + ChartLine, + ChartThemeColor, + ChartVoronoiContainer, + getCustomTheme +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + symbol?: { type: string }; + x?: string; + y?: number; +} + +export const ChartTooltipLeftAligned: React.FunctionComponent = () => { + // Victory theme properties only + const themeProps = { + voronoi: { + style: { + labels: { + textAnchor: 'start' // Align tooltip labels left + } + } + } + }; + + // Applies theme color and variant to base theme + const myCustomTheme = getCustomTheme(ChartThemeColor.default, themeProps); + + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} + constrainToVisibleArea + voronoiDimension="x" + /> + } + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart8" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + theme={myCustomTheme} + width={600} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipLegend.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipLegend.tsx new file mode 100644 index 00000000000..c60b74a25f3 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipLegend.tsx @@ -0,0 +1,55 @@ +import { ChartLabel, ChartLegend, ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { Tooltip } from '@patternfly/react-core'; +import { useRef } from 'react'; + +interface PetData { + x: string; + y: number; +} + +export const ChartTooltipLegend: React.FunctionComponent = () => { + // Custom legend label component + // Note: Tooltip wraps children with a div tag, so we add a reference to ChartLabel instead + const LegendLabel = ({ datum, ...rest }) => { + const ref = useRef(null); + return ( + + + + + ); + }; + + // Custom legend component + const getLegend = (legendData) => } />; + + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendComponent={getLegend([{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }])} + legendPosition="bottom" + name="chart7" + padding={{ + bottom: 65, + left: 20, + right: 20, + top: 20 + }} + themeColor={ChartThemeColor.multiOrdered} + width={300} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipVoronoi.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipVoronoi.tsx new file mode 100644 index 00000000000..11afad2adc7 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipVoronoi.tsx @@ -0,0 +1,67 @@ +import { Chart, ChartArea, ChartAxis, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const ChartTooltipVoronoi: React.FunctionComponent = () => { + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]; + + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 3 }, + { name: 'Dogs', x: '2017', y: 4 }, + { name: 'Dogs', x: '2018', y: 5 }, + { name: 'Dogs', x: '2019', y: 6 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 1 }, + { name: 'Birds', x: '2016', y: 2 }, + { name: 'Birds', x: '2017', y: 3 }, + { name: 'Birds', x: '2018', y: 2 }, + { name: 'Birds', x: '2019', y: 4 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={200} + maxDomain={{ y: 9 }} + name="chart1" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + width={800} + > + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipWrappedChart.tsx b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipWrappedChart.tsx new file mode 100644 index 00000000000..b56f1b69b6e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartTooltip/examples/ChartTooltipWrappedChart.tsx @@ -0,0 +1,54 @@ +import { ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts/victory'; +import { Button, Tooltip, TooltipPosition } from '@patternfly/react-core'; +import { useState } from 'react'; + +interface Data { + x: string; + y: number; +} + +export const ChartTooltipWrappedChart: React.FunctionComponent = () => { + const [isVisible, setIsVisible] = useState(false); + + const showTooltip = () => { + setIsVisible(!isVisible); + }; + + const data: Data[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + + return ( +
    +
    + My custom tooltip
    } + isVisible={isVisible} + position={TooltipPosition.right} + trigger="manual" + > + null} + name="chart10" + > + null} + subTitle="of 100 GBps" + title="45%" + /> + + +
    +
    + +
    +
    + ); +}; diff --git a/packages/react-charts/src/components/ChartTooltip/examples/chart-tooltip.css b/packages/react-charts/src/victory/components/ChartTooltip/examples/chart-tooltip.css similarity index 100% rename from packages/react-charts/src/components/ChartTooltip/examples/chart-tooltip.css rename to packages/react-charts/src/victory/components/ChartTooltip/examples/chart-tooltip.css diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-container.tsx b/packages/react-charts/src/victory/components/ChartUtils/chart-container.tsx new file mode 100644 index 00000000000..8d45f2d9f6f --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-container.tsx @@ -0,0 +1,52 @@ +import chart_container_cursor_line_Fill from '@patternfly/react-tokens/dist/esm/chart_container_cursor_line_Fill'; +import { ContainerType, createContainer as victoryCreateContainer } from 'victory-create-container'; +import { ChartCursorTooltip } from '../ChartCursorTooltip/ChartCursorTooltip'; +import { ChartLabel } from '../ChartLabel/ChartLabel'; +import { LineSegment } from 'victory-core'; + +/** + * Makes a container component with multiple behaviors. It allows you to effectively combine any two + * containers of type 'brush', 'cursor', 'selection', 'voronoi', or 'zoom'. Default container props are applied to + * support the PatternFly theme. + * + * Each behavior must be one of the following strings: 'brush', 'cursor', 'selection', 'voronoi', and 'zoom'. The + * resulting container uses the events from both behaviors. For example, if both behaviors use the click event (like + * zoom and selection) the combined container will trigger both behaviors' events on each click. + * + * Note: Order of the behaviors matters in a few cases. It is recommended to use 'zoom' before any other behaviors: for + * example, createContainer('zoom', 'voronoi') instead of createContainer('voronoi', 'zoom'). + * + * See https://formidable.com/open-source/victory/docs/create-container + * + * @param {string} behaviorA 'brush', 'cursor', 'selection', 'voronoi', or 'zoom' + * @param {string} behaviorB 'brush', 'cursor', 'selection', 'voronoi', or 'zoom' + * @public + */ +export const createContainer = (behaviorA: ContainerType, behaviorB: ContainerType) => { + const Container: any = victoryCreateContainer(behaviorA, behaviorB); + const isCursor = behaviorA === 'cursor' || behaviorB === 'cursor'; + const isVoronoi = behaviorA === 'voronoi' || behaviorB === 'voronoi'; + + const containerWrapper = (props: any) => { + const containerProps = { + ...(isCursor && { + cursorLabelComponent: , + cursorComponent: ( + + ) + }), + ...(isVoronoi && { labelComponent: }), + ...props + }; + return ; + }; + containerWrapper.defaultEvents = Container.defaultEvents; + containerWrapper.displayName = Container.displayName; + containerWrapper.role = Container.role; + + return containerWrapper; +}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-domain.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-domain.ts similarity index 89% rename from packages/react-charts/src/components/ChartUtils/chart-domain.ts rename to packages/react-charts/src/victory/components/ChartUtils/chart-domain.ts index a8bdcc7be53..b53e4d81ea8 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-domain.ts +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-domain.ts @@ -1,4 +1,3 @@ -import * as React from 'react'; import { Data, DataGetterPropType } from 'victory-core'; interface DomainInterface { @@ -18,12 +17,21 @@ interface SourcesInterface { }[]; } +/** + * Chart domain interface + * + * @private Not intended as public API and subject to change + */ export interface ChartDomain { x: [number, number]; y: [number, number]; } -// Returns the min and max domain for given data +/** + * Returns the min and max domain for given data + * + * @private Not intended as public API and subject to change + */ export const getDomain = ({ data, maxDomain, minDomain, x, y }: DomainInterface): ChartDomain => { // x-domain let xLow = 0; @@ -92,9 +100,14 @@ export const getDomain = ({ data, maxDomain, minDomain, x, y }: DomainInterface) return { x: [xLow, xHigh], y: [yLow, yHigh] }; }; +/** + * Returns the domain for given min and max properties + * + * @private Not intended as public API and subject to change + */ export const getDomains = ({ maxDomain, minDomain, sources }: SourcesInterface): ChartDomain => { const domains: ChartDomain[] = []; - sources.forEach(source => { + sources.forEach((source) => { const { data: compData = source.data } = source.component ? source.component.props : undefined; const domain = getDomain({ data: compData, diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-helpers.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-helpers.ts new file mode 100644 index 00000000000..a1e04b29ad6 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-helpers.ts @@ -0,0 +1,32 @@ +// Misc util functions + +interface ChartClassNameInterface { + className?: string; +} + +/** + * Copied from exenv + * + * @private Not intended as public API and subject to change + */ +export const canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); + +/** + * Returns the class name that will be applied to the outermost div rendered by the chart's container + * + * @private Not intended as public API and subject to change + */ +export const getClassName = ({ className }: ChartClassNameInterface) => { + let cleanClassName; + + // Workaround for VictoryContainer class name + if (className) { + cleanClassName = className + .replace(/VictoryContainer/g, '') + .replace(/pf-v6-c-chart/g, '') + .replace(/pf-c-chart/g, '') + .replace(/\s+/g, ' ') + .trim(); + } + return cleanClassName && cleanClassName.length ? `pf-v6-c-chart ${cleanClassName}` : 'pf-v6-c-chart'; +}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-interactive-legend.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-interactive-legend.ts similarity index 79% rename from packages/react-charts/src/components/ChartUtils/chart-interactive-legend.ts rename to packages/react-charts/src/victory/components/ChartUtils/chart-interactive-legend.ts index 4c9733c26a0..c1124422a97 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-interactive-legend.ts +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-interactive-legend.ts @@ -1,6 +1,6 @@ -/* eslint-disable camelcase */ import chart_area_Opacity from '@patternfly/react-tokens/dist/esm/chart_area_Opacity'; -import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; +import chart_global_label_Fill from '@patternfly/react-tokens/dist/esm/chart_global_label_Fill'; +import { Helpers } from 'victory-core'; interface ChartInteractiveLegendInterface { // The names or groups of names associated with each data series @@ -16,16 +16,20 @@ interface ChartInteractiveLegendInterface { interface ChartInteractiveLegendExtInterface extends ChartInteractiveLegendInterface { omitIndex?: number; // Used to omit child names when attaching events - target?: 'data' | 'labels'; // Event target + target?: 'data' | 'labels' | 'parent'; // Event target } -// Returns child names for each series, except given ID index +/** + * Returns child names for each series, except given ID index + * + * @private Not intended as public API and subject to change + */ const getChildNames = ({ chartNames, omitIndex }: ChartInteractiveLegendExtInterface) => { const result = [] as any; - chartNames.map((chartName: any, index: number) => { + chartNames.forEach((chartName: any, index: number) => { if (index !== omitIndex) { if (Array.isArray(chartName)) { - chartName.forEach(name => result.push(name)); + chartName.forEach((name) => result.push(name)); } else { result.push(chartName); } @@ -34,10 +38,15 @@ const getChildNames = ({ chartNames, omitIndex }: ChartInteractiveLegendExtInter return result; }; -// Returns events for an interactive legend +/** + * Returns events for an interactive legend + * + * @param props See ChartInteractiveLegendInterface + * @public + */ export const getInteractiveLegendEvents = (props: ChartInteractiveLegendInterface) => [ - ...getInteractiveLegendTargetEvents({ ...props, target: 'data' }), - ...getInteractiveLegendTargetEvents({ ...props, target: 'labels' }) + ...getInteractiveLegendTargetEvents({ ...props, target: 'data' }), // Legend symbols + ...getInteractiveLegendTargetEvents({ ...props, target: 'labels' }) // Legend labels ]; // Returns legend items, except given ID index @@ -51,16 +60,20 @@ const getInteractiveLegendItems = ({ chartNames, omitIndex }: ChartInteractiveLe return result; }; -// Returns styles for interactive legend items +/** + * Returns styles for interactive legend items + * + * @private Not intended as public API and subject to change + */ export const getInteractiveLegendItemStyles = (hidden = false) => !hidden ? {} : { labels: { - fill: chart_color_black_500.value + fill: chart_global_label_Fill.var }, symbol: { - fill: chart_color_black_500.value, + fill: chart_global_label_Fill.var, type: 'eyeSlash' } }; @@ -117,13 +130,16 @@ const getInteractiveLegendTargetEvents = ({ : ({ // Skip if hidden style: - props.padAngle !== undefined // Support for pie chart + props.slice !== undefined // Support for pie chart ? { - ...props.style, - ...(index !== props.index && { opacity: chart_area_Opacity.value }) + ...Helpers.evaluateStyle(props.style, props), + ...(index !== props.slice.index && { opacity: chart_area_Opacity.value }), + ...(props.data[props.slice.index]._fill && { + fill: props.data[props.slice.index]._fill + }) } : { - ...props.style, + ...Helpers.evaluateStyle(props.style, props), opacity: chart_area_Opacity.value } } as any) @@ -139,7 +155,7 @@ const getInteractiveLegendTargetEvents = ({ : { // Skip if hidden style: { - ...props.style, + ...Helpers.evaluateStyle(props.style, props), opacity: chart_area_Opacity.value } } @@ -156,7 +172,7 @@ const getInteractiveLegendTargetEvents = ({ : { // Skip if hidden style: { - ...props.style, + ...Helpers.evaluateStyle(props.style, props), opacity: chart_area_Opacity.value } }; @@ -173,14 +189,14 @@ const getInteractiveLegendTargetEvents = ({ }, { // Restore all legend item symbols associated with this event - childName: 'legend', + childName: legendName, target: 'data', eventKey: legendItems, mutation: () => null as any }, { // Restore all legend item labels associated with this event - childName: 'legend', + childName: legendName, target: 'labels', eventKey: legendItems, mutation: () => null as any diff --git a/packages/react-charts/src/components/ChartUtils/chart-label.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-label.ts similarity index 81% rename from packages/react-charts/src/components/ChartUtils/chart-label.ts rename to packages/react-charts/src/victory/components/ChartUtils/chart-label.ts index 87194bce629..fb1a70922c8 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-label.ts +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-label.ts @@ -1,6 +1,7 @@ import { Helpers, TextSize } from 'victory-core'; import { getPieOrigin } from './chart-origin'; -import { ChartCommonStyles, ChartThemeDefinition } from '../ChartTheme'; +import { ChartCommonStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; interface ChartBulletLabelInterface { dx?: number; // Horizontal shift from the x coordinate @@ -29,11 +30,19 @@ interface ChartLabelTextSizeInterface { theme: ChartThemeDefinition; // The theme that will be applied to the chart } -// Returns x coordinate for bullet labels +/** + * Returns x coordinate for bullet labels + * + * @private Not intended as public API and subject to change + */ export const getBulletLabelX = ({ chartWidth, dx = 0, labelPosition }: ChartBulletLabelInterface) => labelPosition === 'top' && chartWidth ? Math.round(chartWidth / 2) : dx; -// Returns y coordinate for bullet labels +/** + * Returns y coordinate for bullet labels + * + * @private Not intended as public API and subject to change + */ export const getBulletLabelY = ({ chartHeight, dy = 0, labelPosition }: ChartBulletLabelInterface) => { switch (labelPosition) { case 'bottom': @@ -45,7 +54,11 @@ export const getBulletLabelY = ({ chartHeight, dy = 0, labelPosition }: ChartBul } }; -// Returns x coordinate for pie labels +/** + * Returns x coordinate for pie labels + * + * @private Not intended as public API and subject to change + */ export const getPieLabelX = ({ dx = 0, height, @@ -75,7 +88,11 @@ export const getPieLabelX = ({ } }; -// Returns x coordinate for pie labels +/** + * Returns x coordinate for pie labels + * + * @private Not intended as public API and subject to change + */ export const getPieLabelY = ({ dy = 0, height, labelPosition, padding, width }: ChartPieLabelInterface) => { const origin = getPieOrigin({ height, padding, width }); const radius = Helpers.getRadius({ height, width, padding }); @@ -91,7 +108,11 @@ export const getPieLabelY = ({ dy = 0, height, labelPosition, padding, width }: } }; -// Returns an approximate size for the give text +/** + * Returns an approximate size for the give text + * + * @private Not intended as public API and subject to change + */ export const getLabelTextSize = ({ text, theme }: ChartLabelTextSizeInterface): { height: number; width: number } => { const style: any = theme.legend.style.labels; diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-legend.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-legend.ts new file mode 100644 index 00000000000..6319a05e5cc --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-legend.ts @@ -0,0 +1,540 @@ +import { cloneElement } from 'react'; +import defaults from 'lodash/defaults'; +import { Helpers, TextSize } from 'victory-core'; +import { ElementPadding } from 'victory-core/src/victory-util/helpers'; +import { VictoryLegend } from 'victory-legend'; +import { ChartLegendProps } from '../ChartLegend/ChartLegend'; +import { ChartCommonStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getLabelTextSize } from '../ChartUtils/chart-label'; +import { getPieOrigin } from './chart-origin'; +interface ChartLegendInterface { + allowWrap?: boolean; // Allow legend items to wrap to the next line + chartType?: string; // The type of chart (e.g., pie) to lookup for props + colorScale?: any; // The color scale that will be applied to the chart + dx?: number; // Horizontal shift from the x coordinate + dy?: number; // Vertical shift from the x coordinate + height: number; // Overall height of SVG + legendComponent: React.ReactElement; // The base legend component to render + orientation?: 'horizontal' | 'vertical'; // Orientation of legend + padding: ElementPadding; // Chart padding + patternScale?: string[]; // Legend symbol patterns + position: 'bottom' | 'bottom-left' | 'right'; // The legend position + theme: ChartThemeDefinition; // The theme that will be applied to the chart + themeColor?: string; // The theme color that will be applied to the chart + width: number; // Overall width of SVG +} + +interface ChartLegendDimensionsInterface { + legendData: any[]; // The legend data used to determine width + legendOrientation: 'horizontal' | 'vertical'; // Orientation of legend + legendProps: ChartLegendProps; // Legend properties + theme: ChartThemeDefinition; // The theme that will be applied to the chart +} + +interface ChartLegendPositionInterface { + chartType?: string; // The type of chart (e.g., pie) to lookup for props + dx?: number; // Horizontal shift from the x coordinate + dy?: number; // Vertical shift from the x coordinate + height?: number; // Overall height of SVG + legendData: any[]; // The legend data used to determine width + legendOrientation: 'horizontal' | 'vertical'; // Orientation of legend + legendPosition: 'bottom' | 'bottom-left' | 'right'; // Position of legend + legendProps: any; // The legend props used to determine width + padding?: ElementPadding; // Chart padding + theme: ChartThemeDefinition; // The theme that will be applied to the chart + width?: number; // Overall width of SVG +} + +interface ChartLegendTextMaxSizeInterface { + legendData: any[]; // The legend data used to determine width + theme: ChartThemeDefinition; // The theme that will be applied to the chart +} + +/** + * Returns the max text length in a legend data set to calculate the x offset for right aligned legends. + * + * @private Not intended as public API and subject to change + */ +export const getLegendMaxTextWidth = (legendData: any[], theme: ChartThemeDefinition) => { + let legendXOffset = 0; + legendData.map((data: any) => { + const labelWidth = getLabelTextSize({ text: data.name, theme }).width; + if (labelWidth > legendXOffset) { + legendXOffset = labelWidth; + } + }); + return legendXOffset; +}; + +/** + * Returns a legend which has been positioned per the given chart properties + * + * @private Not intended as public API and subject to change + */ +export const getComputedLegend = ({ + allowWrap = true, + chartType = 'chart', + colorScale, + dx = 0, + dy = 0, + height, + legendComponent, + padding, + patternScale, + position = ChartCommonStyles.legend.position, + theme, + themeColor, + width, + + // destructure last + orientation = theme.legend.orientation as any +}: ChartLegendInterface) => { + // Get the number of legend items per row + const legendItemsProps = legendComponent.props ? legendComponent.props : {}; + const legendItemsPerRow = allowWrap + ? getLegendItemsPerRow({ + dx, + height, + legendData: legendItemsProps.data, + legendOrientation: legendItemsProps.legendOrientation ? legendItemsProps.legendOrientation : orientation, + legendPosition: position, + legendProps: legendItemsProps, + padding, + theme, + width + }) + : undefined; + + // Include new itemsPerRow prop when determining x and y position + const legendPositionProps = defaults({}, legendComponent.props, { + itemsPerRow: legendItemsPerRow + }); + + const legendX = getLegendX({ + chartType, + dx, + height, + legendData: legendPositionProps.data, + legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation, + legendPosition: position, + legendProps: legendPositionProps, + padding, + theme, + width + }); + + const legendY = getLegendY({ + chartType, + dy, + height, + legendData: legendPositionProps.data, + legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation, + legendProps: legendPositionProps, + legendPosition: position, + padding, + theme, + width + }); + + // Clone legend with updated props + const legendProps = defaults({}, legendComponent.props, { + colorScale, + itemsPerRow: legendItemsPerRow, + orientation, + patternScale, + standalone: false, + theme, + themeColor, + x: legendX > 0 ? legendX : 0, + y: legendY > 0 ? legendY : 0 + }); + return cloneElement(legendComponent, legendProps); +}; + +/** + * Returns legend dimensions + * + * @private Not intended as public API and subject to change + */ +export const getLegendDimensions = ({ + legendData, + legendOrientation, + legendProps, + theme +}: ChartLegendDimensionsInterface) => { + if (legendData || legendProps.data) { + return (VictoryLegend as any).getDimensions({ + data: legendData, + orientation: legendOrientation, + theme, + ...legendProps // override above + }); + } + return {}; +}; + +/** + * Returns true if the legend is smaller than its container + * + * @private Not intended as public API and subject to change + */ +const doesLegendFit = ({ + dx = 0, + height, + legendPosition, + legendData, + legendOrientation, + legendProps, + padding, + theme, + width +}: ChartLegendPositionInterface) => { + const { left, right } = Helpers.getPadding(padding); + const chartSize = { + height, // Fixed size + width: width - left - right + }; + const legendDimensions = getLegendDimensions({ + legendData, + legendOrientation, + legendProps, + theme + }); + + let occupiedWidth = 0; + switch (legendPosition) { + case 'bottom-left': + occupiedWidth = left + dx; + break; + case 'right': + occupiedWidth = chartSize.width + ChartCommonStyles.legend.margin + left + dx; + break; + default: + occupiedWidth = dx; + break; + } + return width - occupiedWidth > legendDimensions.width; +}; + +/** + * Returns the number of legend items per row + * + * @private Not intended as public API and subject to change + */ +const getLegendItemsPerRow = ({ + dx, + height, + legendPosition, + legendData, + legendOrientation, + legendProps, + padding, + theme, + width +}: ChartLegendPositionInterface) => { + let itemsPerRow = legendData ? legendData.length : 0; + for (let i = itemsPerRow; i > 0; i--) { + const fits = doesLegendFit({ + dx, + height, + legendPosition, + legendData, + legendOrientation, + legendProps: { + ...legendProps, + itemsPerRow: i + }, + padding, + theme, + width + }); + if (fits) { + itemsPerRow = i; + break; + } + } + return itemsPerRow; +}; + +/** + * Returns the extra height required to accommodate wrapped legend items + * + * @private Not intended as public API and subject to change + */ +export const getLegendItemsExtraHeight = ({ + legendData, + legendOrientation, + legendProps, + theme +}: ChartLegendDimensionsInterface) => { + // Get legend dimensions + const legendDimensions = getLegendDimensions({ + legendData, + legendOrientation, + legendProps, + theme + }); + + // Get legend dimensions without any wrapped items + const legendDimensionsNoWrap = getLegendDimensions({ + legendData, + legendOrientation, + legendProps: { + ...legendProps, + itemsPerRow: undefined + }, + theme + }); + + return Math.abs(legendDimensions.height - legendDimensionsNoWrap.height); +}; + +/** + * Returns x coordinate for legend + * + * @private Not intended as public API and subject to change + */ +const getLegendX = ({ chartType, ...rest }: ChartLegendPositionInterface) => + chartType === 'pie' ? getPieLegendX(rest) : getChartLegendX(rest); + +/** + * Returns y coordinate for legend + * + * @private Not intended as public API and subject to change + */ +const getLegendY = ({ chartType, ...rest }: ChartLegendPositionInterface) => { + switch (chartType) { + case 'pie': + return getPieLegendY(rest); + case 'bullet': + return getBulletLegendY(rest); + default: + return getChartLegendY(rest); + } +}; + +/** + * Returns y coordinate for bullet legends + * + * @private Not intended as public API and subject to change + */ +const getBulletLegendY = ({ + dy = 0, + height, + legendPosition, + legendData, + legendOrientation, + legendProps, + padding, + theme, + width +}: ChartLegendPositionInterface) => { + const { left, right } = Helpers.getPadding(padding); + const chartSize = { + height, // Fixed size + width: width - left - right + }; + + switch (legendPosition) { + case 'bottom': + case 'bottom-left': + return chartSize.height + ChartCommonStyles.legend.margin + dy; + case 'right': { + // Legend height with padding + const legendDimensions = getLegendDimensions({ + legendData, + legendOrientation, + legendProps, + theme + }); + const legendPadding = (legendDataArr: any[]) => (legendDataArr && legendDataArr.length > 0 ? 17 : 0); + return (chartSize.height - legendDimensions.height) / 2 + legendPadding(legendData); + } + default: + return dy; + } +}; + +/** + * Returns x coordinate for chart legends + * + * @private Not intended as public API and subject to change + */ +const getChartLegendX = ({ + dx = 0, + height, + legendData, + legendOrientation, + legendPosition, + legendProps, + padding, + theme, + width +}: ChartLegendPositionInterface) => { + const { top, bottom, left, right } = Helpers.getPadding(padding); + const chartSize = { + height: Math.abs(height - (bottom + top)), + width: Math.abs(width - (left + right)) + }; + const legendDimensions = getLegendDimensions({ + legendData, + legendOrientation, + legendProps, + theme + }); + + switch (legendPosition) { + case 'bottom': + return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx; + case 'bottom-left': + return left + dx; + case 'right': + return chartSize.width + ChartCommonStyles.legend.margin + left + dx; + default: + return dx; + } +}; + +/** + * Returns y coordinate for chart legends + * + * @private Not intended as public API and subject to change + */ +const getChartLegendY = ({ + dy = 0, + height, + legendPosition, + legendData, + legendOrientation, + legendProps, + padding, + theme, + width +}: ChartLegendPositionInterface) => { + const { top, bottom, left, right } = Helpers.getPadding(padding); + const chartSize = { + height: Math.abs(height - (bottom + top)), + width: Math.abs(width - (left + right)) + }; + + switch (legendPosition) { + case 'bottom': + case 'bottom-left': + return chartSize.height + ChartCommonStyles.legend.margin * 2 + top + dy; + case 'right': { + // Legend height with padding + const legendDimensions = getLegendDimensions({ + legendData, + legendOrientation, + legendProps, + theme + }); + const originX = chartSize.height / 2 + top; + const legendPadding = (legendDataArr: any[]) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0); + return originX - legendDimensions.height / 2 + legendPadding(legendData); + } + default: + return dy; + } +}; + +/** + * Returns x coordinate for pie legends + * + * @private Not intended as public API and subject to change + */ +const getPieLegendX = ({ + dx = 0, + height, + legendData, + legendOrientation, + legendPosition, + legendProps, + padding, + theme, + width +}: ChartLegendPositionInterface) => { + const origin = getPieOrigin({ height, padding, width }); + const radius = Helpers.getRadius({ height, width, padding }); + const legendDimensions = getLegendDimensions({ + legendData, + legendOrientation, + legendProps, + theme + }); + + switch (legendPosition) { + case 'bottom': + return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx; + case 'right': + return origin.x + ChartCommonStyles.label.margin + dx + radius; + default: + return dx; + } +}; + +/** + * Returns y coordinate for pie legends + * + * @private Not intended as public API and subject to change + */ +const getPieLegendY = ({ + dy = 0, + height, + legendPosition, + legendData, + legendOrientation, + legendProps, + padding, + theme, + width +}: ChartLegendPositionInterface) => { + const origin = getPieOrigin({ height, padding, width }); + const radius = Helpers.getRadius({ height, width, padding }); + + switch (legendPosition) { + case 'bottom': + return origin.y + ChartCommonStyles.legend.margin + radius + dy; + case 'right': { + // Legend height with padding + const legendDimensions = getLegendDimensions({ + legendData, + legendOrientation, + legendProps, + theme + }); + const legendPadding = (legendDataArr: any[]) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0); + return origin.y - legendDimensions.height / 2 + legendPadding(legendData); + } + default: + return dy; + } +}; + +/** + * Returns an approximation of longest text width based on legend styles + * + * @private Not intended as public API and subject to change + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const getMaxLegendTextSize = ({ legendData, theme }: ChartLegendTextMaxSizeInterface) => { + const style: any = theme && theme.legend && theme.legend.style ? theme.legend.style.labels : undefined; + if (!(legendData && legendData.length)) { + return 0; + } + + let result = ''; + legendData.forEach((data) => { + if (data.name && data.name.length > result.length) { + result = data.name; + } + }); + + // The approximateTextSize function returns height and width, but Victory incorrectly typed it as number + const adjustedTextSize: any = TextSize.approximateTextSize(result, { + ...style + }); + + return adjustedTextSize.width; +}; diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-origin.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-origin.ts new file mode 100644 index 00000000000..e2cce4d9e8e --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-origin.ts @@ -0,0 +1,24 @@ +import { Helpers } from 'victory-core'; + +interface ChartPieOriginInterface { + height: number; // Chart height + padding: any; // Chart padding + width: number; // Chart width +} + +/** + * Returns the origin for pie based charts. For example, something with a radius such as pie, donut, donut utilization, + * and donut threshold. + * + * @private Not intended as public API and subject to change + */ +export const getPieOrigin = ({ height, padding, width }: ChartPieOriginInterface) => { + const { top, bottom, left, right } = Helpers.getPadding(padding); + const radius = Helpers.getRadius({ height, width, padding }); + const offsetX = (width - radius * 2 - left - right) / 2; + const offsetY = (height - radius * 2 - top - bottom) / 2; + return { + x: radius + left + offsetX, + y: radius + top + offsetY + }; +}; diff --git a/packages/react-charts/src/components/ChartUtils/chart-padding.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-padding.ts similarity index 76% rename from packages/react-charts/src/components/ChartUtils/chart-padding.ts rename to packages/react-charts/src/victory/components/ChartUtils/chart-padding.ts index 4ece7bf085a..a56ef159973 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-padding.ts +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-padding.ts @@ -1,5 +1,10 @@ import { PaddingProps } from 'victory-core'; +/** + * Helper function to return padding style properties + * + * @private Not intended as public API and subject to change + */ export const getPaddingForSide = ( side: 'bottom' | 'left' | 'right' | 'top', padding: PaddingProps, @@ -10,6 +15,5 @@ export const getPaddingForSide = ( } else if (typeof padding == 'object' && Object.keys(padding).length > 0) { return padding[side] || 0; } - return getPaddingForSide(side, fallback, 0); }; diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-patterns.tsx b/packages/react-charts/src/victory/components/ChartUtils/chart-patterns.tsx new file mode 100644 index 00000000000..177f3975a9f --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-patterns.tsx @@ -0,0 +1,397 @@ +import { Children, cloneElement, Fragment, isValidElement, useMemo } from 'react'; +import uniqueId from 'lodash/uniqueId'; +import cloneDeep from 'lodash/cloneDeep'; + +interface PatternPropsInterface { + children?: any; + colorScale?: any; + hasPatterns?: boolean | boolean[]; + isPatternDefs?: boolean; + offset?: number; + patternId?: string; + patternScale?: string[]; + patternUnshiftIndex?: number; + themeColor?: string; + themeColorScale?: string[]; +} + +/** + * Patterns were pulled from v3.0.3 of the script below, which uses the MIT license. + * See https://github.com/highcharts/pattern-fill/blob/master/pattern-fill-v2.js + * + * @private Not intended as public API and subject to change + */ +const patterns: any = [ + // Set 1 + { + // Left diagonal lines + d: 'M 0 0 L 5 5 M 4.5 -0.5 L 5.5 0.5 M -0.5 4.5 L 0.5 5.5', + height: 5, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + patternTransform: 'scale(1.4 1.4)', + strokeWidth: 2, + width: 5, + x: 0, + y: 0 + }, + { + // Right diagonal lines + d: 'M 0 5 L 5 0 M -0.5 0.5 L 0.5 -0.5 M 4.5 5.5 L 5.5 4.5', + height: 5, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + patternTransform: 'scale(1.4 1.4)', + strokeWidth: 2, + width: 5, + x: 0, + y: 0 + }, + { + // Vertical offset line + d: 'M 2 0 L 2 5 M 4 0 L 4 5', + height: 5, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + patternTransform: 'scale(1.4 1.4)', + strokeWidth: 2, + width: 5, + x: 0, + y: 0 + }, + { + // Horizontal lines + d: 'M 0 2 L 5 2 M 0 4 L 5 4', + height: 5, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + patternTransform: 'scale(1.4 1.4)', + strokeWidth: 2, + width: 5, + x: 0, + y: 0 + }, + { + // Vertical wave + d: 'M 0 1.5 L 2.5 1.5 L 2.5 0 M 2.5 5 L 2.5 3.5 L 5 3.5', + height: 5, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + patternTransform: 'scale(1.4 1.4)', + strokeWidth: 2, + width: 5, + x: 0, + y: 0 + }, + + // Set 2 + { + // Horizontal wave + d: 'M 0 0 L 5 10 L 10 0', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + }, + { + // Squares + d: 'M 3 3 L 8 3 L 8 8 L 3 8 Z', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + }, + { + // Circles + d: 'M 5 5 m -4 0 a 4 4 0 1 1 8 0 a 4 4 0 1 1 -8 0', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + }, + { + // Left diagonal lines (thin) + d: 'M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + }, + { + // Right diagonal lines (thin) + d: 'M 0 10 L 10 0 M -1 1 L 1 -1 M 9 11 L 11 9', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + }, + + // Set 3 + { + // Diamonds + d: 'M 2 5 L 5 2 L 8 5 L 5 8 Z', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + }, + { + // Thin vertical lines + d: 'M 3 0 L 3 10 M 8 0 L 8 10', + height: 5, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + patternTransform: 'scale(1.4 1.4)', + strokeWidth: 2, + width: 5, + x: 0, + y: 0 + }, + { + // Left zig zag + d: 'M 10 3 L 5 3 L 5 0 M 5 10 L 5 7 L 0 7', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + }, + { + // Thin horizontal lines + d: 'M 0 3 L 10 3 M 0 8 L 10 8', + height: 5, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + patternTransform: 'scale(1.4 1.4)', + strokeWidth: 2, + width: 5, + x: 0, + y: 0 + }, + { + // Right zig zag + d: 'M 0 3 L 5 3 L 5 0 M 5 10 L 5 7 L 10 7', + height: 10, + fill: 'none', + patternContentUnits: 'userSpaceOnUse', + patternUnits: 'userSpaceOnUse', + strokeWidth: 2, + width: 10, + x: 0, + y: 0 + } +]; + +/** + * Helper function to return a pattern ID + * + * @private Not intended as public API and subject to change + */ +const getPatternId = () => uniqueId('pf-pattern'); + +/** + * Helper function to return pattern defs ID + * + * @private Not intended as public API and subject to change + */ +const getPatternDefsId = (prefix: string, index: number) => { + const id = `${prefix}:${index}`; + return id; +}; + +/** + * Helper function to return pattern defs + * + * @private Not intended as public API and subject to change + */ +export const getPatternDefs = ({ + colorScale, + offset = 0, + patternId, + patternUnshiftIndex = 0 +}: PatternPropsInterface) => { + const defaultPatterns = [...patterns]; + + // Move the given pattern index to top of scale, used to sync patterns with ChartDonutThreshold + if (patternUnshiftIndex > 0 && patternUnshiftIndex < defaultPatterns.length) { + defaultPatterns.unshift(defaultPatterns.splice(patternUnshiftIndex, 1)[0]); + } + + // This is wrapped in an empty tag so Victory does not apply child props to defs + const defs = ( + + + {colorScale.map((color: string, index: number) => { + const { + d, + fill, + stroke = color, + strokeWidth, + ...rest + } = defaultPatterns[(index + offset) % defaultPatterns.length]; + const id = getPatternDefsId(patternId, index); + return ( + + + + ); + })} + + + ); + return defs; +}; + +/** + * Helper function to return pattern IDs to use as color scale + * + * @private Not intended as public API and subject to change + */ +const getPatternScale = (colorScale: string[], patternId: string) => + colorScale.map((val: any, index: number) => `url(#${getPatternDefsId(patternId, index)})`); + +/** + * Helper function to return default color scale + * + * @private Not intended as public API and subject to change + */ +const getDefaultColorScale = (colorScale: string[], themeColorScale: string[]) => { + const result: string[] = []; + const colors = colorScale ? colorScale : themeColorScale; + + colors.forEach((val) => result.push(val)); + return result; +}; + +/** + * Helper function to return default pattern scale + * + * @private Not intended as public API and subject to change + */ +const getDefaultPatternScale = ({ colorScale, patternId, patternScale }: PatternPropsInterface) => { + if (patternScale) { + return patternScale; + } + const defaultPatternScale = getPatternScale(colorScale, patternId); + return defaultPatternScale && defaultPatternScale.length > 0 ? defaultPatternScale : undefined; +}; + +/** + * Merge pattern IDs with `data.fill` property, used by interactive pie chart legend + * + * @private Not intended as public API and subject to change + */ +export const mergePatternData = (data: any, patternScale: string[]) => { + if (!patternScale) { + return data; + } + return data.map((datum: any, index: number) => { + const pattern = patternScale[index % patternScale.length]; + return { + ...(pattern && { _fill: pattern }), + ...datum + }; + }); +}; + +/** + * Helper function to return default pattern props + * + * @private Not intended as public API and subject to change + */ +export const useDefaultPatternProps = ({ + colorScale, + hasPatterns, + patternScale, + themeColorScale +}: PatternPropsInterface) => { + const defaultColorScale = getDefaultColorScale(colorScale, themeColorScale); + let defaultPatternScale = cloneDeep(patternScale); + let isPatternDefs = !patternScale && hasPatterns !== undefined; + const patternId = useMemo(() => (isPatternDefs ? getPatternId() : undefined), [isPatternDefs]); + + if (isPatternDefs) { + defaultPatternScale = getDefaultPatternScale({ + colorScale: defaultColorScale, + patternId, + patternScale + }); + } + + // Initialize pattern visibility + if (Array.isArray(hasPatterns)) { + for (let i = 0; i < defaultPatternScale.length; i++) { + if (!(i < hasPatterns.length && hasPatterns[i])) { + defaultPatternScale[i] = null; + } + } + } else if (hasPatterns === false) { + defaultPatternScale = undefined; + isPatternDefs = false; + } + return { defaultColorScale, defaultPatternScale, isPatternDefs, patternId }; +}; + +/** + * Helper function to render children with patterns + * + * @private Not intended as public API and subject to change + */ +export const renderChildrenWithPatterns = ({ children, patternScale, themeColor }: PatternPropsInterface) => + Children.toArray(children).map((child, index) => { + if (isValidElement(child)) { + const { ...childProps } = child.props as any; + const style = childProps.style ? { ...childProps.style } : {}; + + // Merge pattern IDs with `style.data.fill` property + if (patternScale) { + const pattern = patternScale[index % patternScale.length]; + style.data = { + ...(pattern && { fill: pattern }), + ...style.data + }; + } + const _child = cloneElement(child, { + ...(patternScale && { patternScale }), + ...(themeColor && { themeColor }), + ...childProps, + style // Override child props + }); + return _child; + } + return child; + }); diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-theme-types.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-theme-types.ts new file mode 100644 index 00000000000..0a9a25bc432 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-theme-types.ts @@ -0,0 +1,195 @@ +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getComponentTheme, getTheme } from './chart-theme'; +import merge from 'lodash/merge'; + +/** + * Returns axis theme + * + * @private Not intended as public API and subject to change + */ +export const getAxisTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.axis); +}; + +/** + * Returns bullet chart theme + * + * @private Not intended as public API and subject to change + */ +export const getBulletTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bullet); +}; + +/** + * Returns comparative error measure theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletComparativeErrorMeasureTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletComparativeErrorMeasure); +}; + +/** + * Returns comparative measure theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletComparativeMeasureTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletComparativeMeasure); +}; + +/** + * Returns comparative warning measure theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletComparativeWarningMeasureTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletComparativeWarningMeasure); +}; + +/** + * Returns group title theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletGroupTitleTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletGroupTitle); +}; + +/** + * Returns primary dot measure theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletPrimaryDotMeasureTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletPrimaryDotMeasure); +}; + +/** + * Returns primary negative measure theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletPrimaryNegativeMeasureTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletPrimaryNegativeMeasure); +}; + +/** + * Returns primary segmented measure theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletPrimarySegmentedMeasureTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletPrimarySegmentedMeasure); +}; + +/** + * Returns qualitative range theme for bullet chart + * + * @private Not intended as public API and subject to change + */ +export const getBulletQualitativeRangeTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletQualitativeRange); +}; + +/** + * Returns theme for Chart component + * + * @private Not intended as public API and subject to change + */ +export const getChartTheme = (themeColor: string, showAxis: boolean): ChartThemeDefinition => { + const theme = getTheme(themeColor); + + if (!showAxis) { + theme.axis.padding = 0; + theme.axis.style.axis.fill = 'transparent'; + theme.axis.style.axis.stroke = 'transparent'; + theme.axis.style.grid.fill = 'transparent'; + theme.axis.style.grid.stroke = 'transparent'; + theme.axis.style.ticks.fill = 'transparent'; + theme.axis.style.ticks.stroke = 'transparent'; + theme.axis.style.tickLabels.fill = 'transparent'; + } + return theme; +}; + +/** + * Returns donut theme + * + * @private Not intended as public API and subject to change + */ +export const getDonutTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.donut); +}; + +/** + * Returns dynamic donut threshold theme + * + * @private Not intended as public API and subject to change + */ +export const getDonutThresholdDynamicTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.donutThresholdDynamic); +}; + +/** + * Returns static donut threshold theme + * + * @private Not intended as public API and subject to change + */ +export const getDonutThresholdStaticTheme = (themeColor: string, invert?: boolean): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + const theme = merge(baseTheme, componentTheme.donutThresholdStatic); + + if (invert && baseTheme.pie.colorScale instanceof Array) { + const colorScale = [...componentTheme.donutThresholdStatic.pie.colorScale]; + theme.pie.colorScale = merge(baseTheme.pie.colorScale, colorScale.reverse()); + } + return theme; +}; + +/** + * Returns donut utilization theme + * + * @private Not intended as public API and subject to change + */ +export const getDonutUtilizationTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.donutUtilization); +}; + +/** + * Returns threshold theme + * + * @private Not intended as public API and subject to change + */ +export const getThresholdTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.threshold); +}; diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-theme.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-theme.ts new file mode 100644 index 00000000000..9e52be9a229 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-theme.ts @@ -0,0 +1,117 @@ +import cloneDeep from 'lodash/cloneDeep'; +import merge from 'lodash/merge'; +import { ChartThemeColor } from '../ChartTheme/ChartThemeColor'; +import { ChartThemeDefinition, ChartComponentThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartBaseTheme, ChartBaseComponentTheme } from '../ChartTheme/ChartThemeTypes'; +import { BlueColorTheme, BlueColorComponentTheme } from '../ChartTheme/themes/colors/blue-theme'; +import { TealColorTheme, TealColorComponentTheme } from '../ChartTheme/themes/colors/teal-theme'; +import { YellowColorTheme, YellowColorComponentTheme } from '../ChartTheme/themes/colors/yellow-theme'; +import { GrayColorTheme, GrayColorComponentTheme } from '../ChartTheme/themes/colors/gray-theme'; +import { GreenColorTheme, GreenColorComponentTheme } from '../ChartTheme/themes/colors/green-theme'; +import { SkeletonColorTheme, SkeletonColorComponentTheme } from '../ChartTheme/themes/colors/skeleton-theme'; +import { + MultiColorOrderedTheme, + MultiColorOrderedComponentTheme +} from '../ChartTheme/themes/colors/multi-ordered-theme'; +import { + MultiColorUnorderedTheme, + MultiColorUnorderedComponentTheme +} from '../ChartTheme/themes/colors/multi-unordered-theme'; +import { OrangeColorTheme, OrangeColorComponentTheme } from '../ChartTheme/themes/colors/orange-theme'; +import { PurpleColorTheme, PurpleColorComponentTheme } from '../ChartTheme/themes/colors/purple-theme'; + +/** + * Apply custom properties to base and color themes + * + * @param themeColor The theme color to merge with custom theme + * @param customTheme The custom theme to merge + * @public + */ +export const getCustomTheme = (themeColor: string, customTheme: ChartThemeDefinition): ChartThemeDefinition => + merge(getTheme(themeColor), customTheme); + +/** + * Returns base theme for given color + * + * @public + */ +export const getTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = cloneDeep(ChartBaseTheme); + return merge(baseTheme, getThemeColors(themeColor)); +}; + +/** + * Returns base component theme for given color + * + * @private Not intended as public API and subject to change + */ +export const getComponentTheme = (themeColor: string): ChartComponentThemeDefinition => { + const theme = cloneDeep(ChartBaseComponentTheme); + return merge(theme, getThemeComponentColors(themeColor)); +}; + +/** + * Returns theme colors + * + * @public + */ +export const getThemeColors = (themeColor: string) => { + switch (themeColor) { + case ChartThemeColor.blue: + return BlueColorTheme; + case ChartThemeColor.teal: + return TealColorTheme; + case ChartThemeColor.yellow: + return YellowColorTheme; + case ChartThemeColor.gray: + return GrayColorTheme; + case ChartThemeColor.green: + return GreenColorTheme; + case ChartThemeColor.multi: + case ChartThemeColor.multiOrdered: + return MultiColorOrderedTheme; + case ChartThemeColor.multiUnordered: + return MultiColorUnorderedTheme; + case ChartThemeColor.orange: + return OrangeColorTheme; + case ChartThemeColor.purple: + return PurpleColorTheme; + case ChartThemeColor.skeleton: + return SkeletonColorTheme; + default: + return BlueColorTheme; + } +}; + +/** + * Returns theme component colors + * + * @private Not intended as public API and subject to change + */ +export const getThemeComponentColors = (themeColor: string) => { + switch (themeColor) { + case ChartThemeColor.blue: + return BlueColorComponentTheme; + case ChartThemeColor.teal: + return TealColorComponentTheme; + case ChartThemeColor.yellow: + return YellowColorComponentTheme; + case ChartThemeColor.gray: + return GrayColorComponentTheme; + case ChartThemeColor.green: + return GreenColorComponentTheme; + case ChartThemeColor.multi: + case ChartThemeColor.multiOrdered: + return MultiColorOrderedComponentTheme; + case ChartThemeColor.multiUnordered: + return MultiColorUnorderedComponentTheme; + case ChartThemeColor.orange: + return OrangeColorComponentTheme; + case ChartThemeColor.purple: + return PurpleColorComponentTheme; + case ChartThemeColor.skeleton: + return SkeletonColorComponentTheme; + default: + return BlueColorComponentTheme; + } +}; diff --git a/packages/react-charts/src/victory/components/ChartUtils/chart-tooltip.ts b/packages/react-charts/src/victory/components/ChartUtils/chart-tooltip.ts new file mode 100644 index 00000000000..323fa2f3911 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartUtils/chart-tooltip.ts @@ -0,0 +1,302 @@ +import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; +import { Helpers, OrientationTypes, StringOrNumberOrCallback } from 'victory-core'; +import { ChartLegendProps } from '../ChartLegend/ChartLegend'; +import { ChartLegendTooltipStyles } from '../ChartTheme/ChartStyles'; +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { getLegendDimensions } from './chart-legend'; + +import merge from 'lodash/merge'; + +interface ChartCursorTooltipCenterOffsetInterface { + offsetCursorDimensionX?: boolean; // Adjust the tooltip to appear to the right of the vertical cursor + offsetCursorDimensionY?: boolean; // Adjust the tooltip to appear above the horizontal cursor + theme?: ChartThemeDefinition; +} + +interface ChartCursorTooltipPoniterOrientationInterface { + horizontal?: boolean; + theme?: ChartThemeDefinition; +} + +interface ChartLegendTooltipFlyoutInterface { + legendData: any; + legendOrientation?: 'horizontal' | 'vertical'; + legendProps?: any; + minSpacing?: number; + text?: StringOrNumberOrCallback | string[] | number[]; + theme: ChartThemeDefinition; +} + +interface ChartLegendTooltipVisibleDataInterface { + activePoints?: any[]; + colorScale?: string[]; + legendData: any; + patternScale?: string[]; // Legend symbol patterns + text?: StringOrNumberOrCallback | string[] | number[]; + textAsLegendData?: boolean; + theme: ChartThemeDefinition; +} + +interface ChartLegendTooltipVisibleTextInterface { + activePoints?: any[]; + legendData: any; + text: StringOrNumberOrCallback | string[] | number[]; +} + +/** + * When using a cursor container, the tooltip can be offset from the cursor point. If offsetCursorDimensionX is true, + * the tooltip will appear to the right the vertical cursor. If offsetCursorDimensionY is true, the tooltip will appear + * above the vertical cursor. + * + * @private Not intended as public API and subject to change + */ +export const getCursorTooltipCenterOffset = ({ + offsetCursorDimensionX = false, + offsetCursorDimensionY = false, + theme +}: ChartCursorTooltipCenterOffsetInterface) => { + const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength, undefined) : 10; + const offsetX = ({ center, flyoutWidth, width }: any) => { + const offset = flyoutWidth / 2 + pointerLength; + return width > center.x + flyoutWidth + pointerLength ? offset : -offset; + }; + const offsetY = ({ center, flyoutHeight, width }: any) => { + const offset = flyoutHeight / 2 + pointerLength; + return width > center.y + flyoutHeight + pointerLength ? -offset : offset; + }; + return { + x: offsetCursorDimensionX ? offsetX : 0, + y: offsetCursorDimensionY ? offsetY : 0 + }; +}; + +/** + * When using a cursor container, the tooltip pointer orientation can be adjusted as the cursor approaches the edge of + * the chart. If horizontal is true, the tooltip pointer will either be 'left' or 'right'. If horizontal is true, the + * tooltip pointer will either be 'top' or 'bottom'. + * + * @private Not intended as public API and subject to change + */ +export const getCursorTooltipPoniterOrientation = ({ + horizontal = true, + theme +}: ChartCursorTooltipPoniterOrientationInterface): ((props: any) => OrientationTypes) => { + const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength, undefined) : 10; + const orientationX = ({ center, flyoutWidth, width }: any): OrientationTypes => + width > center.x + flyoutWidth + pointerLength ? 'left' : 'right'; + const orientationY = ({ center, flyoutHeight, height }: any): OrientationTypes => + height > center.y + flyoutHeight + pointerLength ? 'top' : 'bottom'; + return horizontal ? orientationX : orientationY; +}; + +/** + * Returns props associated with legend data + * + * @private Not intended as public API and subject to change + */ +export const getLegendTooltipDataProps = (props: ChartLegendProps) => + merge( + { + borderPadding: 0, + gutter: 0, + orientation: 'vertical', + padding: 0, + rowGutter: 0, + style: { + labels: { + fill: ChartLegendTooltipStyles.label.fill, + lineHeight: 0.275, + padding: 0 + }, + title: { + fill: ChartLegendTooltipStyles.label.fill, + padding: 0 + } + } + }, + { ...props } + ); + +/** + * Returns the legend height and width + * + * @private Not intended as public API and subject to change + */ +export const getLegendTooltipSize = ({ + legendData, + legendOrientation = 'vertical', + legendProps, + minSpacing = 2, // Adjust min spacing, see https://issues.redhat.com/browse/COST-5648 + text = '', + theme +}: ChartLegendTooltipFlyoutInterface) => { + const textEvaluated = Helpers.evaluateProp(text, undefined); + const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; + + // Find max char lengths + let maxDataLength = 0; + let maxTextLength = 0; + _text.map((item, index) => { + if (typeof item === 'number') { + return; + } + + if (item) { + if (item.length > maxTextLength) { + maxTextLength = item.length; + } + const hasData = legendData && legendData[index] && legendData[index].name !== undefined; + if (hasData) { + if (legendData[index].name.length > maxDataLength) { + maxDataLength = legendData[index].name.length; + } + } + } + }); + + // Set length to ensure minimum spacing between label and value + const maxLength = maxDataLength + maxTextLength + minSpacing; + + // Get spacing to help align legend labels and text values + const spacer = 'x'; + const getSpacing = (legendLabel: string, textLabel: string) => { + let spacing = '\u00A0'; + if (maxLength === 0) { + return spacing; + } + const legendLabelChars = legendLabel ? legendLabel.length : 0; + const textLabelChars = textLabel ? textLabel.length : 0; + const maxChars = legendLabelChars + textLabelChars; + + // Add spacer + while (spacing.length < maxLength - maxChars) { + spacing += spacer; + } + return spacing; + }; + + // Format all text (similar to below) to help determine overall width. + // + // {name: "Cats no data"} + // {name: "Dogs 1"} + // {name: "Birds 4"} + // {name: "Mice 3"} + const data = _text.map((label, index) => { + if (typeof label === 'number') { + return; + } + + const hasData = legendData && legendData[index] && legendData[index].name !== undefined; + const spacing = hasData ? getSpacing(legendData[index].name, label) : ''; + + return { + name: `${hasData ? legendData[index].name : ''}${spacing}${label}` + }; + }); + + // Replace whitespace with spacer char for consistency in width + const formattedData = data.map((val) => ({ + name: val.name.replace(/ /g, spacer) + })); + + // This should include both legend data and text + const widthDimensions = getLegendDimensions({ + legendData: formattedData, + legendOrientation, + legendProps, + theme + }); + // This should only use text. The row gutter changes when displaying all "no data" messages + const heightDimensions = getLegendDimensions({ + legendData: _text.map((name) => ({ name })), + legendOrientation, + legendProps, + theme + }); + return { + height: heightDimensions.height, + width: widthDimensions.width > 0 ? widthDimensions.width : 0 + }; +}; + +/** + * Returns visible legend data, while syncing color scale. If textAsLegendData is true, the text prop is used as + * legend data so y values can be passed individually to the label component + * + * @private Not intended as public API and subject to change + */ +export const getLegendTooltipVisibleData = ({ + activePoints, + colorScale, + legendData, + patternScale, + text, + textAsLegendData = false, + theme +}: ChartLegendTooltipVisibleDataInterface) => { + const textEvaluated = Helpers.evaluateProp(text, undefined); + const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; + const result = []; + + // Sync data with interactive legends + if (legendData) { + let index = -1; + for (let i = 0; i < legendData.length; i++) { + const data = legendData[i]; + const activePoint = activePoints ? activePoints.find((item) => item.childName === data.childName) : ''; + if ( + !activePoint || + (data.symbol && data.symbol.type === 'eyeSlash' && data.symbol.fill === chart_color_black_500.var) + ) { + continue; // Skip hidden data + } + if (index++ < _text.length - 1) { + const themeColor = + theme && theme.legend && theme.legend.colorScale + ? theme.legend.colorScale[i % theme.legend.colorScale.length] + : undefined; + const color = colorScale ? colorScale[i % colorScale.length] : themeColor; // Sync color scale + const pattern = patternScale ? patternScale[i % patternScale.length] : undefined; + result.push({ + name: textAsLegendData ? _text[index] : data.name, + symbol: { + fill: pattern ? pattern : color, + ...data.symbol + } + }); + } + } + } + return result; +}; + +/** + * Returns visible text for interactive legends + * + * @private Not intended as public API and subject to change + */ +export const getLegendTooltipVisibleText = ({ + activePoints, + legendData, + text +}: ChartLegendTooltipVisibleTextInterface) => { + const textEvaluated = Helpers.evaluateProp(text, undefined); + const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; + const result = []; + if (legendData) { + let index = -1; + for (const data of legendData) { + const activePoint = activePoints ? activePoints.find((item) => item.childName === data.childName) : ''; + if ( + !activePoint || + (data.symbol && data.symbol.type === 'eyeSlash' && data.symbol.fill === chart_color_black_500.var) + ) { + continue; // Skip hidden data + } + if (index++ < _text.length - 1) { + result.push(_text[index]); + } + } + } + return result as string[] | number[]; +}; diff --git a/packages/react-charts/src/victory/components/ChartVoronoiContainer/ChartVoronoContainer.test.tsx b/packages/react-charts/src/victory/components/ChartVoronoiContainer/ChartVoronoContainer.test.tsx new file mode 100644 index 00000000000..33bd35b5ad4 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartVoronoiContainer/ChartVoronoContainer.test.tsx @@ -0,0 +1,36 @@ +import { render } from '@testing-library/react'; +import { ChartArea } from '../ChartArea/ChartArea'; +import { ChartGroup } from '../ChartGroup/ChartGroup'; +import { ChartVoronoiContainer } from './ChartVoronoiContainer'; + +Object.values([true, false]).forEach(() => { + test('ChartVoronoiContainer', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); + +test('renders container via ChartGroup', () => { + const { asFragment } = render( + } height={200} width={200}> + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-charts/src/components/ChartVoronoiContainer/ChartVoronoiContainer.tsx b/packages/react-charts/src/victory/components/ChartVoronoiContainer/ChartVoronoiContainer.tsx similarity index 87% rename from packages/react-charts/src/components/ChartVoronoiContainer/ChartVoronoiContainer.tsx rename to packages/react-charts/src/victory/components/ChartVoronoiContainer/ChartVoronoiContainer.tsx index c23e2ae203b..4c5b063a6ad 100644 --- a/packages/react-charts/src/components/ChartVoronoiContainer/ChartVoronoiContainer.tsx +++ b/packages/react-charts/src/victory/components/ChartVoronoiContainer/ChartVoronoiContainer.tsx @@ -1,19 +1,20 @@ -import * as React from 'react'; +import { cloneElement } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { OriginType } from 'victory-core'; import { VictoryVoronoiContainer, VictoryVoronoiContainerProps } from 'victory-voronoi-container'; -import { ChartThemeDefinition } from '../ChartTheme'; -import { ChartTooltip } from '../ChartTooltip'; -import { getClassName, getTheme } from '../ChartUtils'; - -export enum ChartVoronoiDimension { - x = 'x', - y = 'y' -} +import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartTooltip } from '../ChartTooltip/ChartTooltip'; +import { getClassName } from '../ChartUtils/chart-helpers'; +import { getTheme } from '../ChartUtils/chart-theme'; /** - * See https://github.com/FormidableLabs/victory/blob/master/packages/victory-core/src/index.d.ts - * and https://github.com/FormidableLabs/victory/blob/master/packages/victory-voronoi-container/src/index.d.ts + * ChartVoronoiContainer adds the ability to associate a mouse position with the data point(s) closest to it. When this + * container is added to a chart, changes in mouse position will add the active prop to data and label components + * closest to the current mouse position. The closeness of data points to a given position is determined by calculating + * a voronoi diagram based on the data of every child VictoryVoronoiContainer renders. This container is useful for + * adding hover interactions, like tooltips, to small data points, or charts with dense or overlapping data. + * + * See https://github.com/FormidableLabs/victory/blob/main/packages/victory-voronoi-container/src/index.d.ts */ export interface ChartVoronoiContainerProps extends VictoryVoronoiContainerProps { /** @@ -32,16 +33,17 @@ export interface ChartVoronoiContainerProps extends VictoryVoronoiContainerProps */ activateLabels?: boolean; /** - * he children prop specifies the child or children that will be rendered within the container. It will be set by + * The children prop specifies the child or children that will be rendered within the container. It will be set by * whatever Victory component is rendering the container. * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ - children?: React.ReactElement | React.ReactElement[]; + children?: React.ReactElement | React.ReactElement[]; /** - * The className prop specifies a className that will be applied to the outer-most div rendered by the container + * The className prop specifies a className that will be applied to the outermost div rendered by the container */ className?: string; /** @@ -61,7 +63,7 @@ export interface ChartVoronoiContainerProps extends VictoryVoronoiContainerProps * the description, the more usable it will be for people using screen readers. * This prop defaults to an empty string. * - * @example "Golden retreivers make up 30%, Labs make up 25%, and other dog breeds are + * @example "Golden retrievers make up 30%, Labs make up 25%, and other dog breeds are * not represented above 5% each." */ desc?: string; @@ -137,6 +139,7 @@ export interface ChartVoronoiContainerProps extends VictoryVoronoiContainerProps * * Note: This prop should not be set manually. * + * @private Not intended as public API and subject to change * @hide */ polar?: boolean; @@ -147,7 +150,7 @@ export interface ChartVoronoiContainerProps extends VictoryVoronoiContainerProps * render in the portal container. This prop defaults to Portal, and should only be overridden when changing rendered * elements from SVG to another type of element e.g., react-native-svg elements. */ - portalComponent?: React.ReactElement; + portalComponent?: React.ReactElement; /** * The portalZIndex prop determines the z-index of the div enclosing the portal component. If a portalZIndex prop is * not set, the z-index of the enclosing div will be set to 99. @@ -194,14 +197,6 @@ export interface ChartVoronoiContainerProps extends VictoryVoronoiContainerProps * @example themeColor={ChartThemeColor.blue} */ themeColor?: string; - /** - * Specifies the theme variant. Valid values are 'dark' or 'light' - * - * Note: Not compatible with theme prop - * - * @example themeVariant={ChartThemeVariant.light} - */ - themeVariant?: string; /** * The voronoiBlacklist prop is used to specify a list of components to ignore when calculating a * shared voronoi diagram. Components with a name prop matching an element in the voronoiBlacklist @@ -234,15 +229,14 @@ export const ChartVoronoiContainer: React.FunctionComponent, // Note that Victory provides its own tooltip component here ...rest }: ChartVoronoiContainerProps) => { const chartClassName = getClassName({ className }); - const chartLabelComponent = React.cloneElement(labelComponent, { + const chartLabelComponent = cloneElement(labelComponent, { constrainToVisibleArea, theme, ...labelComponent.props @@ -255,7 +249,6 @@ export const ChartVoronoiContainer: React.FunctionComponent +
    + +
    + +
    +
    +
    +`; + +exports[`ChartVoronoiContainer 2`] = ` + +
    + +
    + +
    +
    +
    +`; + +exports[`renders container via ChartGroup 1`] = ` + +
    + + + + + + + + + + + + + + + + + + +
    + +
    +
    +
    +`; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsAll.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsAll.tsx new file mode 100644 index 00000000000..448f5f9b7a2 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsAll.tsx @@ -0,0 +1,101 @@ +import { ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsAll: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [extraHeight, setExtraHeight] = useState(0); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + const handleLegendAllowWrap = (newExtraHeight) => { + if (newExtraHeight !== extraHeight) { + setExtraHeight(newExtraHeight); + } + }; + const getHeight = (baseHeight) => baseHeight + extraHeight; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + const height = getHeight(260); + + const data: PetData[] = [ + { x: 'Cats', y: 6 }, + { x: 'Dogs', y: 6 }, + { x: 'Birds', y: 6 }, + { x: 'Fish', y: 6 }, + { x: 'Rabbits', y: 6 }, + { x: 'Squirels', y: 6 }, + { x: 'Chipmunks', y: 6 }, + { x: 'Bats', y: 6 }, + { x: 'Ducks', y: 6 }, + { x: 'Geese', y: 6 }, + { x: 'Bobcats', y: 6 }, + { x: 'Foxes', y: 6 }, + { x: 'Coyotes', y: 6 }, + { x: 'Deer', y: 6 }, + { x: 'Bears', y: 10 } + ]; + + const legendData: PetData[] = [ + { name: 'Cats: 6' }, + { name: 'Dogs: 6' }, + { name: 'Birds: 6' }, + { name: 'Fish: 6' }, + { name: 'Rabbits: 6' }, + { name: 'Squirels: 6' }, + { name: 'Chipmunks: 6' }, + { name: 'Bats: 6' }, + { name: 'Ducks: 6' }, + { name: 'Geese: 6' }, + { name: 'Bobcat: 6' }, + { name: 'Foxes: 6' }, + { name: 'Coyotes: 6' }, + { name: 'Deer: 6' }, + { name: 'Bears: 6' } + ]; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendAllowWrap={handleLegendAllowWrap} + legendPosition="bottom" + name="chart12" + padding={{ + bottom: getHeight(50), // This must be adjusted to maintain the aspec ratio + left: 20, + right: 20, + top: 20 + }} + themeColor={ChartThemeColor.multiOrdered} + width={width} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsBarChart.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsBarChart.tsx new file mode 100644 index 00000000000..584be31d4c6 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsBarChart.tsx @@ -0,0 +1,80 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartGroup, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsBarChart: React.FunctionComponent = () => { + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendPosition="bottom" + hasPatterns + height={275} + name="chart2" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + themeColor={ChartThemeColor.purple} + width={450} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsBasicPieChart.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsBasicPieChart.tsx new file mode 100644 index 00000000000..b14049f62a6 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsBasicPieChart.tsx @@ -0,0 +1,41 @@ +import { ChartPie } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsBasicPieChart: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart1" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomColorScale.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomColorScale.tsx new file mode 100644 index 00000000000..c2a3e10f414 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomColorScale.tsx @@ -0,0 +1,44 @@ +import { ChartPie } from '@patternfly/react-charts/victory'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsCustomColorScale: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + return ( +
    + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart10" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomDefs.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomDefs.tsx new file mode 100644 index 00000000000..583a72dadc8 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomDefs.tsx @@ -0,0 +1,75 @@ +import { ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsCustomDefs: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( +
    + + + + + + + + + + + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart11" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + patternScale={['url("#pattern1")', 'url("#pattern2")', null]} + themeColor={ChartThemeColor.multiUnordered} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomVisibility.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomVisibility.tsx new file mode 100644 index 00000000000..8b5f46345a7 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsCustomVisibility.tsx @@ -0,0 +1,50 @@ +import { ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsCustomVisibility: React.FunctionComponent = () => { + const data: PetData[] = [ + { x: 'Cats', y: 15 }, + { x: 'Dogs', y: 15 }, + { x: 'Birds', y: 15 }, + { x: 'Fish', y: 25 }, + { x: 'Rabbits', y: 30 } + ]; + const legendData: PetData[] = [ + { name: 'Cats: 15' }, + { name: 'Dogs: 15' }, + { name: 'Birds: 15' }, + { name: 'Fish: 25' }, + { name: 'Rabbits: 30' } + ]; + + return ( +
    + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart9" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + themeColor={ChartThemeColor.multiUnordered} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutChart.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutChart.tsx new file mode 100644 index 00000000000..45bf8af7574 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutChart.tsx @@ -0,0 +1,44 @@ +import { ChartDonut, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsDonutChart: React.FunctionComponent = () => { + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + return ( +
    + `${datum.x}: ${datum.y}%`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart4" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + subTitle="Pets" + title="100" + themeColor={ChartThemeColor.yellow} + width={350} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutUtilizationChart.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutUtilizationChart.tsx new file mode 100644 index 00000000000..e32e688be1c --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutUtilizationChart.tsx @@ -0,0 +1,40 @@ +import { ChartDonutUtilization, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface Data { + x?: string; + y?: number; + name?: string; +} + +export const PatternsDonutUtilizationChart: React.FunctionComponent = () => { + const data: Data = { x: 'Storage capacity', y: 45 }; + const legendData: Data[] = [{ name: `Storage capacity: 45%` }, { name: 'Unused' }]; + + return ( +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendPosition="bottom" + name="chart5" + padding={{ + bottom: 65, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + subTitle="of 100 GBps" + title="45%" + themeColor={ChartThemeColor.green} + thresholds={[{ value: 60 }, { value: 90 }]} + width={300} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutUtilizationThreshold.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutUtilizationThreshold.tsx new file mode 100644 index 00000000000..20de55e1613 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsDonutUtilizationThreshold.tsx @@ -0,0 +1,52 @@ +import { ChartDonutThreshold, ChartDonutUtilization, ChartThemeColor } from '@patternfly/react-charts/victory'; + +interface Data { + x?: string; + y?: number; + name?: string; +} + +export const PatternsDonutUtilizationThreshold: React.FunctionComponent = () => { + const data1: Data[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const data2: Data = { x: 'Storage capacity', y: 45 }; + const legendData: Data[] = [ + { name: `Storage capacity: 45%` }, + { name: 'Warning threshold at 60%' }, + { name: 'Danger threshold at 90%' } + ]; + + return ( +
    + (datum.x ? datum.x : null)} + name="chart6" + padding={{ + bottom: 65, // Adjusted to accommodate legend + left: 20, + right: 20, + top: 20 + }} + width={675} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendPosition="bottom" + subTitle="of 100 GBps" + title="45%" + themeColor={ChartThemeColor.orange} + /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsInteractiveAreaChart.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsInteractiveAreaChart.tsx new file mode 100644 index 00000000000..a310c6b50ed --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsInteractiveAreaChart.tsx @@ -0,0 +1,184 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartLegend, + ChartLegendTooltip, + ChartScatter, + ChartThemeColor, + createContainer, + getInteractiveLegendEvents, + getInteractiveLegendItemStyles +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +export const PatternsInteractiveAreaChart: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [hiddenSeries, setHiddenSeries] = useState(new Set()); + const [width, setWidth] = useState(0); + + const series = [ + { + datapoints: [ + { x: '2015', y: 3 }, + { x: '2016', y: 4 }, + { x: '2017', y: 8 }, + { x: '2018', y: 6 } + ], + legendItem: { name: 'Cats' } + }, + { + datapoints: [ + { x: '2015', y: 2 }, + { x: '2016', y: 3 }, + { x: '2017', y: 4 }, + { x: '2018', y: 5 }, + { x: '2019', y: 6 } + ], + legendItem: { name: 'Dogs' } + }, + { + datapoints: [ + { x: '2015', y: 1 }, + { x: '2016', y: 2 }, + { x: '2017', y: 3 }, + { x: '2018', y: 2 }, + { x: '2019', y: 4 } + ], + legendItem: { name: 'Birds' } + } + ]; + + // Returns groups of chart names associated with each data series + const getChartNames = () => { + const result = []; + series.map((_, index) => { + // Each group of chart names are hidden / shown together + result.push([`area-${index}`, `scatter-${index}`]); + }); + return result; + }; + + // Returns onMouseOver, onMouseOut, and onClick events for the interactive legend + const getEvents = () => + getInteractiveLegendEvents({ + chartNames: getChartNames(), + isHidden, + legendName: 'chart8-ChartLegend', + onLegendClick: handleLegendClick + }); + + // Returns legend data styled per hiddenSeries + const getLegendData = () => + series.map((s, index) => ({ + childName: `area-${index}`, // Sync tooltip legend with the series associated with given chart name + ...s.legendItem, // name property + ...getInteractiveLegendItemStyles(hiddenSeries.has(index)) // hidden styles + })); + + // Hide each data series individually + const handleLegendClick = (props) => { + if (!hiddenSeries.delete(props.index)) { + hiddenSeries.add(props.index); + } + setHiddenSeries(new Set(hiddenSeries)); + }; + + // Set chart width per current window size + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + // Returns true if data series is hidden + const isHidden = (index) => hiddenSeries.has(index); + + const isDataAvailable = () => hiddenSeries.size !== series.length; + + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + + const cursorVoronoiContainer = ( + (datum.childName.includes('area-') && datum.y !== null ? `${datum.y}` : null)} + labelComponent={ datum.x} />} + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={50} + /> + ); + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + // Tips: + // 1. Omitting hidden components will reassign color scale, use null data instead or custom colors + // 2. Set domain or tick axis labels to account for when all data series are hidden + // 3. Omit tooltip for ChartScatter component by checking childName prop + // 4. Omit tooltip when all data series are hidden + // 5. Clone original container to ensure tooltip events are not lost when data series are hidden / shown + const container = cloneElement(cursorVoronoiContainer, { + disable: !isDataAvailable() + }); + + return ( +
    +
    + } + legendPosition="bottom-left" + name="chart8" + padding={{ + bottom: 75, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + {series.map((s, index) => ( + (active ? 5 : 3)} + /> + ))} + + + {series.map((s, index) => ( + + ))} + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsInteractivePieChart.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsInteractivePieChart.tsx new file mode 100644 index 00000000000..b5ba8388fa3 --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsInteractivePieChart.tsx @@ -0,0 +1,101 @@ +import { + Chart, + ChartLegend, + ChartThemeColor, + ChartPie, + getInteractiveLegendEvents, + getInteractiveLegendItemStyles +} from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + x?: string; + y?: number; +} + +export const PatternsInteractivePieChart: React.FunctionComponent = () => { + const [hiddenSeries, setHiddenSeries] = useState(new Set()); + + const series = [ + { + datapoints: { x: 'Cats', y: 25 }, + legendItem: { name: 'Cats: 35' } + }, + { + datapoints: { x: 'Dogs', y: 25 }, + legendItem: { name: 'Dogs: 25' } + }, + { + datapoints: { x: 'Birds', y: 10 }, + legendItem: { name: 'Birds: 10' } + } + ]; + + // Returns groups of chart names associated with each data series + const getChartNames = () => { + const result = []; + series.map((_, _index) => { + // Provide names for each series hidden / shown -- use the same name for a pie chart + result.push(['pie']); + }); + return result; + }; + + // Returns onMouseOver, onMouseOut, and onClick events for the interactive legend + const getEvents = () => + getInteractiveLegendEvents({ + chartNames: getChartNames(), + isHidden, + legendName: 'chart7-ChartLegend', + onLegendClick: handleLegendClick + }); + + // Returns legend data styled per hiddenSeries + const getLegendData = () => + series.map((s, index) => ({ + ...s.legendItem, // name property + ...getInteractiveLegendItemStyles(hiddenSeries.has(index)) // hidden styles + })); + + // Hide each data series individually + const handleLegendClick = (props) => { + if (!hiddenSeries.delete(props.index)) { + hiddenSeries.add(props.index); + } + setHiddenSeries(new Set(hiddenSeries)); + }; + + // Returns true if data series is hidden + const isHidden = (index) => hiddenSeries.has(index); + + const data: PetData[] = []; + series.map((s, index) => { + data.push(!hiddenSeries.has(index) ? s.datapoints : { y: null }); + }); + + return ( +
    + } + legendPosition="bottom" + name="chart7" + padding={{ + bottom: 65, + left: 20, + right: 20, + top: 20 + }} + showAxis={false} + themeColor={ChartThemeColor.multiUnordered} + width={500} + > + `${datum.x}: ${datum.y}`} name="pie" /> + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/PatternsStackChart.tsx b/packages/react-charts/src/victory/components/Patterns/examples/PatternsStackChart.tsx new file mode 100644 index 00000000000..2b285360cef --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/PatternsStackChart.tsx @@ -0,0 +1,81 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartStack, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + x?: string; + y?: number; + name?: string; +} + +export const PatternsStackChart: React.FunctionComponent = () => { + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + hasPatterns + height={250} + name="chart3" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={ChartThemeColor.green} + width={600} + > + + + + + + + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Patterns/examples/patterns.md b/packages/react-charts/src/victory/components/Patterns/examples/patterns.md new file mode 100644 index 00000000000..a3f4788615f --- /dev/null +++ b/packages/react-charts/src/victory/components/Patterns/examples/patterns.md @@ -0,0 +1,162 @@ +--- +id: Patterns +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartArea', + 'ChartAxis', + 'ChartBar', + 'ChartDonut', + 'ChartDonutThreshold', + 'ChartDonutUtilization', + 'ChartGroup', + 'ChartLegend', + 'ChartLegendTooltip', + 'ChartPie', + 'ChartScatter', + 'ChartStack', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { cloneElement, createRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; +import { + Chart, + ChartArea, + ChartAxis, + ChartBar, + ChartDonut, + ChartDonutThreshold, + ChartDonutUtilization, + ChartGroup, + ChartLegend, + ChartLegendTooltip, + ChartPie, + ChartScatter, + ChartStack, + ChartThemeColor, + ChartVoronoiContainer, + createContainer, + getInteractiveLegendEvents, + getInteractiveLegendItemStyles +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import chart_color_black_500 from '@patternfly/react-tokens/dist/esm/chart_color_black_500'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_green_300 from '@patternfly/react-tokens/dist/esm/chart_color_green_300'; +import chart_color_teal_300 from '@patternfly/react-tokens/dist/esm/chart_color_teal_300'; +import chart_color_yellow_300 from '@patternfly/react-tokens/dist/esm/chart_color_yellow_300'; +import '@patternfly/patternfly/patternfly-charts.css'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic pie chart +```ts file = "PatternsBasicPieChart.tsx" + +``` + +### Bar chart +```ts file = "PatternsBarChart.tsx" + +``` + +### Stack chart +```ts file = "PatternsStackChart.tsx" + +``` + +### Donut chart +```ts file = "PatternsDonutChart.tsx" + +``` + +### Donut utilization chart + +This demonstrates how to hide a pattern for the static, unused portion of the donut utilization chart. + +```ts file = "PatternsDonutUtilizationChart.tsx" + +``` + +### Donut utilization chart with thresholds + +This demonstrates how to apply patterns to thresholds. + +```ts file = "PatternsDonutUtilizationThreshold.tsx" + +``` + +### Interactive legend with pie chart + +This demonstrates how to add an interactive legend to a pie chart using events such as `onMouseOver`, `onMouseOut`, and `onClick`. + +```ts file = "PatternsInteractivePieChart.tsx" + +``` + +### Interactive legend with area chart + +This demonstrates how to add an interactive legend using events such as `onMouseOver`, `onMouseOut`, and `onClick`. + +```ts file = "PatternsInteractiveAreaChart.tsx" + +``` + +### Custom pattern visibility + +This demonstrates how to omit patterns from pie chart segments. + +```ts file = "PatternsCustomVisibility.tsx" + +``` + +### Custom color scale + +This demonstrates how to apply a custom color scale to patterns. + +```ts file = "PatternsCustomColorScale.tsx" + +``` + +### Custom pattern defs + +This demonstrates how to create custom patterns. + +```ts file = "PatternsCustomDefs.tsx" + +``` + +### All patterns +```ts file = "PatternsAll.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartDonut` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartDonutThreshold` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartDonutUtilization` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartLegend` props, see [VictoryLegend](https://formidable.com/open-source/victory/docs/victory-legend) +- For `ChartPie` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartScatter` props, see [VictoryScatter](https://formidable.com/open-source/victory/docs/victory-scatter) +- For `ChartStack` props, see [VictoryStack](https://formidable.com/open-source/victory/docs/victory-stack) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveBullet.tsx b/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveBullet.tsx new file mode 100644 index 00000000000..54d38838e66 --- /dev/null +++ b/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveBullet.tsx @@ -0,0 +1,84 @@ +import { ChartBullet } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +interface Data { + name?: string; + y?: number; +} + +export const ResizeObserverResponsiveBullet: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [extraHeight, setExtraHeight] = useState(0); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + const handleLegendAllowWrap = (newExtraHeight) => { + if (newExtraHeight !== extraHeight) { + setExtraHeight(newExtraHeight); + } + }; + + const getHeight = (baseHeight) => baseHeight + extraHeight; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + const height = getHeight(200); + const comparativeWarningMeasureData: Data[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: Data[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: Data[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]; + const primarySegmentedMeasureLegendData: Data[] = [{ name: 'Measure 1' }, { name: 'Measure 2' }]; + const qualitativeRangeData: Data[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: Data[] = [{ name: 'Range 1' }, { name: 'Range 2' }]; + + return ( +
    + `${datum.name}: ${datum.y}`} + legendAllowWrap={handleLegendAllowWrap} + legendPosition="bottom-left" + maxDomain={{ y: 100 }} + name="chart1" + padding={{ + bottom: 50, + left: 50, + right: 50, + top: 100 // Adjusted to accommodate labels + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Measure details" + title="Text label" + titlePosition="top-left" + width={width} + /> +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveStack.tsx b/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveStack.tsx new file mode 100644 index 00000000000..80af5a32c82 --- /dev/null +++ b/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveStack.tsx @@ -0,0 +1,111 @@ +import { Chart, ChartAxis, ChartBar, ChartStack, ChartTooltip } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +interface Data { + name?: string; + x?: string; + y?: number; +} + +export const ResizeObserverResponsiveStack: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + const bars: Data[] = []; + for (let i = 1; i < 32; i++) { + bars.push({ x: `Aug. ${i}`, y: Math.floor(Math.random() * 6) + 1 }); + } + + const renderSocketBars = () => { + const socketBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Sockets', + label: `${tick.x} Sockets: ${tick.y}` + })); + return } />; + }; + + const renderCoresBars = () => { + const coresBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Cores', + label: `${tick.x} Cores: ${tick.y}` + })); + return } />; + }; + + const renderNodesBars = () => { + const nodesBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Nodes', + label: `${tick.x} Nodes: ${tick.y}` + })); + return } />; + }; + + const getTickValues = (offset = 2) => { + const tickValues: string[] = []; + for (let i = 1; i < 32; i++) { + if (i % offset === 0) { + tickValues.push(`Aug. ${i}`); + } + } + return tickValues; + }; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + const legendData: Data[] = [{ name: 'Sockets' }, { name: 'Cores' }, { name: 'Nodes' }]; + + return ( +
    +
    + + + + + {renderSocketBars()} + {renderCoresBars()} + {renderNodesBars()} + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveThreshold.tsx b/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveThreshold.tsx new file mode 100644 index 00000000000..f5330eaa594 --- /dev/null +++ b/packages/react-charts/src/victory/components/ResizeObserver/examples/ResizeObserverResponsiveThreshold.tsx @@ -0,0 +1,147 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartLegend, + ChartGroup, + ChartThreshold, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; +import { useEffect, useRef, useState } from 'react'; + +interface PetData { + name?: string; + symbol?: { fill: string; type: string }; + x?: number; + y?: number; +} + +export const ResizeObserverResponsiveThreshold: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [extraHeight, setExtraHeight] = useState(0); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + const handleLegendAllowWrap = (newExtraHeight) => { + if (newExtraHeight !== extraHeight) { + setExtraHeight(newExtraHeight); + } + }; + + const getHeight = (baseHeight) => baseHeight + extraHeight; + + const getPadding = () => ({ + bottom: 100 + extraHeight, // Adjusted to accomodate legend + left: 50, + right: 50, + top: 50 + }); + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + const height = getHeight(250); + const data1: PetData[] = [ + { name: 'Cats' }, + { + name: 'Cats Threshold', + symbol: { fill: chart_color_blue_300.var, type: 'threshold' } + }, + { name: 'Birds' }, + { + name: 'Birds Threshold', + symbol: { fill: chart_color_orange_300.var, type: 'threshold' } + } + ]; + + const data2: PetData[] = [ + { name: 'Cats', x: 1, y: 3 }, + { name: 'Cats', x: 2, y: 4 }, + { name: 'Cats', x: 3, y: 8 }, + { name: 'Cats', x: 4, y: 6 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: 1, y: 2 }, + { name: 'Birds', x: 2, y: 3 }, + { name: 'Birds', x: 3, y: 4 }, + { name: 'Birds', x: 4, y: 5 }, + { name: 'Birds', x: 5, y: 6 } + ]; + + const data4: PetData[] = [ + { name: 'Cats Threshold', x: 0, y: 4 }, + { name: 'Cats Threshold', x: 3, y: 4 }, + { name: 'Cats Threshold', x: 3, y: 6 }, + { name: 'Cats Threshold', x: 5, y: 6 } + ]; + + const data5: PetData[] = [ + { name: 'Birds Threshold', x: 0, y: 2 }, + { name: 'Birds Threshold', x: 2, y: 2 }, + { name: 'Birds Threshold', x: 2, y: 3 }, + { name: 'Birds Threshold', x: 5, y: 3 } + ]; + + return ( +
    +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendAllowWrap={handleLegendAllowWrap} + legendPosition="bottom-left" + legendComponent={} + height={height} + name="chart2" + padding={getPadding()} + maxDomain={{ y: 9 }} + themeColor={ChartThemeColor.multiUnordered} + width={width} + > + + + + + + + + + +
    +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/ResizeObserver/examples/resizeObserver.md b/packages/react-charts/src/victory/components/ResizeObserver/examples/resizeObserver.md new file mode 100644 index 00000000000..4c98bbd440c --- /dev/null +++ b/packages/react-charts/src/victory/components/ResizeObserver/examples/resizeObserver.md @@ -0,0 +1,96 @@ +--- +id: Resize observer +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartArea', + 'ChartAxis', + 'ChartBar', + 'ChartBullet', + 'ChartGroup', + 'ChartLegend', + 'ChartStack', + 'ChartThreshold', + 'ChartTooltip', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { useEffect, useRef, useState } from 'react'; +import { + Chart, + ChartArea, + ChartAxis, + ChartBar, + ChartBullet, + ChartGroup, + ChartLegend, + ChartStack, + ChartThemeColor, + ChartThreshold, + ChartTooltip, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import chart_color_orange_300 from '@patternfly/react-tokens/dist/esm/chart_color_orange_300'; +import '@patternfly/patternfly/patternfly-charts.css'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +Charts scale within the parent container by default, so the `width` and `height` props do not actually determine the +width and height of the chart in number of pixels, but instead define an aspect ratio for the chart. The exact number +of pixels will depend on the size of the container the chart is rendered into. In order to maintain the aspect ratio, +the parent container may be set to the same height and/or width. + +## Examples +### Responsive bullet chart with wrapping legend + +This demonstrates how to use a `ResizeObserver` to update the chart's width, while its height remains fixed. The `legendAllowWrap` prop is used to automatically wrap legend items. + +```ts file = "ResizeObserverResponsiveBullet.tsx" + +``` + +### Responsive threshold chart with wrapping legend + +This demonstrates how to use a `ResizeObserver` to update the chart's width, while its height remains fixed. In this example, `itemsPerRow` is used to wrap legend items manually. + +```ts file = "ResizeObserverResponsiveThreshold.tsx" + +``` + +### Responsive stack chart with reducible axis tick labels + +This demonstrates how to use a `ResizeObserver` to update the chart's width, while its height remains fixed. In this example, `fixLabelOverlap` is used to dynamically adjust the number of axis tick labels. + +```ts file = "ResizeObserverResponsiveStack.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- `ChartLegend` may be used as a standalone component, instead of using `legendData` + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartBullet` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartLegend` props, see [VictoryLegend](https://formidable.com/open-source/victory/docs/victory-legend) +- For `ChartLine` props, see [Victoryline](https://formidable.com/open-source/victory/docs/victory-line) +- For `ChartStack` props, see [VictoryStack](https://formidable.com/open-source/victory/docs/victory-stack) +- For `ChartTooltip` props, see [VictoryTooltip](https://formidable.com/open-source/victory/docs/victory-tooltip) +- For `ChartThreshold` props, see [VictoryLine](https://formidable.com/open-source/victory/docs/victory-line) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsAreaChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsAreaChart.tsx new file mode 100644 index 00000000000..f9a758b240f --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsAreaChart.tsx @@ -0,0 +1,85 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { Switch } from '@patternfly/react-core'; +import { useState } from 'react'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const SkeletonsAreaChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 3 }, + { name: 'Dogs', x: '2017', y: 4 }, + { name: 'Dogs', x: '2018', y: 5 }, + { name: 'Dogs', x: '2019', y: 6 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 1 }, + { name: 'Birds', x: '2016', y: 2 }, + { name: 'Birds', x: '2017', y: 3 }, + { name: 'Birds', x: '2018', y: 2 }, + { name: 'Birds', x: '2019', y: 4 } + ]; + + return ( + <> + +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={200} + maxDomain={{ y: 9 }} + name="chart1" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={800} + > + + + + + + + + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBarChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBarChart.tsx new file mode 100644 index 00000000000..35e8c2ceecb --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBarChart.tsx @@ -0,0 +1,92 @@ +import { Switch } from '@patternfly/react-core'; +import { + Chart, + ChartBar, + ChartAxis, + ChartGroup, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const SkeletonsBarChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( + <> + +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domain={{ y: [0, 9] }} + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + name="chart2" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + > + + + + + + + + + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBoxPlotChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBoxPlotChart.tsx new file mode 100644 index 00000000000..6a89f4ca625 --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBoxPlotChart.tsx @@ -0,0 +1,56 @@ +import { Switch } from '@patternfly/react-core'; +import { Chart, ChartAxis, ChartBoxPlot, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + name?: string; + x?: string; + y?: number[]; +} + +export const SkeletonsBoxPlotChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const legendData: PetData[] = [{ name: 'Cats' }]; + const data: PetData[] = [ + { name: 'Cats', x: '2015', y: [1, 2, 3, 5] }, + { name: 'Cats', x: '2016', y: [3, 2, 8, 10] }, + { name: 'Cats', x: '2017', y: [2, 8, 6, 5] }, + { name: 'Cats', x: '2018', y: [1, 3, 2, 9] } + ]; + + return ( + <> + +
    + + + + + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBulletChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBulletChart.tsx new file mode 100644 index 00000000000..27ce6fa524b --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsBulletChart.tsx @@ -0,0 +1,63 @@ +import { Switch } from '@patternfly/react-core'; +import { ChartBullet, ChartLegend, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface Data { + name?: string; + y?: number; +} + +export const SkeletonsBulletChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const comparativeWarningMeasureData: Data[] = [{ name: 'Warning', y: 88 }]; + const comparativeWarningMeasureLegendData: Data[] = [{ name: 'Warning' }]; + const primarySegmentedMeasureData: Data[] = [ + { name: 'Measure', y: 25 }, + { name: 'Measure', y: 60 } + ]; + const primarySegmentedMeasureLegendData: Data[] = [{ name: 'Measure' }, { name: 'Measure' }]; + const qualitativeRangeData: Data[] = [ + { name: 'Range', y: 50 }, + { name: 'Range', y: 75 } + ]; + const qualitativeRangeLegendData: Data[] = [{ name: 'Range' }, { name: 'Range' }]; + + return ( + <> + +
    + `${datum.name}: ${datum.y}`} + legendComponent={} + maxDomain={{ y: 100 }} + name="chart4" + padding={{ + bottom: 50, + left: 150, // Adjusted to accommodate labels + right: 50, + top: 50 + }} + primarySegmentedMeasureData={primarySegmentedMeasureData} + primarySegmentedMeasureLegendData={primarySegmentedMeasureLegendData} + qualitativeRangeData={qualitativeRangeData} + qualitativeRangeLegendData={qualitativeRangeLegendData} + subTitle="Details" + title="Text label" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + /> +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutChart.tsx new file mode 100644 index 00000000000..dcc2b31f7fd --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutChart.tsx @@ -0,0 +1,42 @@ +import { Switch } from '@patternfly/react-core'; +import { ChartDonut, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const SkeletonsDonutChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + + return ( + <> + +
    + `${datum.x}: ${datum.y}%`} + name="chart5" + subTitle="Pets" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + title="100" + /> +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutUtilizationChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutUtilizationChart.tsx new file mode 100644 index 00000000000..1ab3ac3537d --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutUtilizationChart.tsx @@ -0,0 +1,54 @@ +import { Switch } from '@patternfly/react-core'; +import { ChartDonutUtilization, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface Data { + name?: string; + x?: string; + y?: number; +} + +export const SkeletonsDonutUtilizationChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const legendData: Data[] = [{ name: `Storage capacity: 75%` }, { name: 'Unused' }]; + const data: Data = { x: 'GBps capacity', y: 35 }; + + return ( + <> + +
    + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + legendData={legendData} + legendOrientation="vertical" + name="chart6" + padding={{ + bottom: 20, + left: 20, + right: 225, // Adjusted to accommodate legend + top: 20 + }} + subTitle="of 100 GBps" + title="35%" + thresholds={[{ value: 60 }, { value: 90 }]} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={435} + /> +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutUtilizationThreshold.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutUtilizationThreshold.tsx new file mode 100644 index 00000000000..6f46040edac --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsDonutUtilizationThreshold.tsx @@ -0,0 +1,51 @@ +import { Switch } from '@patternfly/react-core'; +import { ChartDonutThreshold, ChartDonutUtilization, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface Data { + x: string; + y: number; +} + +export const SkeletonsDonutUtilizationThreshold: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const data1: Data[] = [ + { x: 'Warning at 60%', y: 60 }, + { x: 'Danger at 90%', y: 90 } + ]; + const data2: Data = { x: 'Storage capacity', y: 45 }; + + return ( + <> + +
    + (datum.x ? datum.x : null)} + name="chart7" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + > + (datum.x ? `${datum.x}: ${datum.y}%` : null)} + subTitle="of 100 GBps" + title="45%" + /> + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsLineChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsLineChart.tsx new file mode 100644 index 00000000000..0a3c54ebecb --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsLineChart.tsx @@ -0,0 +1,105 @@ +import { Switch } from '@patternfly/react-core'; +import { + Chart, + ChartVoronoiContainer, + ChartGroup, + ChartAxis, + ChartLine, + ChartThemeColor +} from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + name?: string; + symbol?: { type: string }; + x?: string; + y?: number; +} + +export const SkeletonsLineChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const legendData: PetData[] = [ + { name: 'Cats' }, + { name: 'Dogs', symbol: { type: 'dash' } }, + { name: 'Birds' }, + { name: 'Mice' } + ]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 3 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 5 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 7 } + ]; + + return ( + <> + +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + maxDomain={{ y: 10 }} + minDomain={{ y: 0 }} + name="chart8" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + > + + + + + + + + + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsPieChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsPieChart.tsx new file mode 100644 index 00000000000..41deb950a77 --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsPieChart.tsx @@ -0,0 +1,52 @@ +import { Switch } from '@patternfly/react-core'; +import { ChartPie, ChartThemeColor } from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const SkeletonsPieChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const data: PetData[] = [ + { x: 'Cats', y: 35 }, + { x: 'Dogs', y: 55 }, + { x: 'Birds', y: 10 } + ]; + const legendData: PetData[] = [{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]; + + return ( + <> + +
    + `${datum.x}: ${datum.y}`} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + name="chart9" + padding={{ + bottom: 20, + left: 20, + right: 140, // Adjusted to accommodate legend + top: 20 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={350} + /> +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsScatterChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsScatterChart.tsx new file mode 100644 index 00000000000..657e0270bd9 --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsScatterChart.tsx @@ -0,0 +1,58 @@ +import { Switch } from '@patternfly/react-core'; +import { + Chart, + ChartVoronoiContainer, + ChartGroup, + ChartAxis, + ChartScatter, + ChartThemeColor +} from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const SkeletonsScatterChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const data: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 4 } + ]; + + return ( + <> + +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + height={275} + maxDomain={{ y: 8 }} + minDomain={{ y: 0 }} + name="chart10" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={450} + > + + + + + + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsStackChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsStackChart.tsx new file mode 100644 index 00000000000..2dcb61460bb --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsStackChart.tsx @@ -0,0 +1,91 @@ +import { Switch } from '@patternfly/react-core'; +import { + Chart, + ChartVoronoiContainer, + ChartAxis, + ChartStack, + ChartBar, + ChartThemeColor +} from '@patternfly/react-charts/victory'; +import { useState } from 'react'; + +interface PetData { + name?: string; + x?: string; + y?: number; +} + +export const SkeletonsStackChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( + <> + +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + domainPadding={{ x: [30, 25] }} + legendData={legendData} + legendOrientation="vertical" + legendPosition="right" + height={250} + name="chart11" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + > + + + + + + + + + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsThresholdChart.tsx b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsThresholdChart.tsx new file mode 100644 index 00000000000..55c8d2ee6a5 --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/SkeletonsThresholdChart.tsx @@ -0,0 +1,102 @@ +import { Switch } from '@patternfly/react-core'; +import { + Chart, + ChartArea, + ChartAxis, + ChartGroup, + ChartLegend, + ChartThemeColor, + ChartThreshold, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; +import { useState } from 'react'; + +interface PetData { + name?: string; + symbol?: { fill: string | undefined; type: string }; + x?: number; + y?: number; +} + +export const SkeletonsThresholdChart: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + const data1: PetData[] = [ + { name: 'Cats' }, + { name: 'Birds' }, + { + name: 'Threshold', + symbol: { fill: isChecked ? undefined : chart_color_blue_300.var, type: 'threshold' } + } + ]; + + const data2: PetData[] = [ + { name: 'Cats', x: 1, y: 3 }, + { name: 'Cats', x: 2, y: 4 }, + { name: 'Cats', x: 3, y: 8 }, + { name: 'Cats', x: 4, y: 6 } + ]; + + const data3: PetData[] = [ + { name: 'Birds', x: 1, y: 2 }, + { name: 'Birds', x: 2, y: 3 }, + { name: 'Birds', x: 3, y: 4 }, + { name: 'Birds', x: 4, y: 5 }, + { name: 'Birds', x: 5, y: 6 } + ]; + + const data4: PetData[] = [ + { name: 'Cats Threshold', x: 0, y: 5 }, + { name: 'Cats Threshold', x: 3, y: 5 }, + { name: 'Cats Threshold', x: 3, y: 7 }, + { name: 'Cats Threshold', x: 5, y: 7 } + ]; + + return ( + <> + +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + legendPosition="bottom-left" + legendComponent={} + height={250} + padding={{ + bottom: 100, // Adjusted to accommodate legend + left: 50, + right: 50, + top: 50 + }} + maxDomain={{ y: 9 }} + name="chart12" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={800} + > + + + + + + + + +
    + + ); +}; diff --git a/packages/react-charts/src/victory/components/Skeletons/examples/skeletons.md b/packages/react-charts/src/victory/components/Skeletons/examples/skeletons.md new file mode 100644 index 00000000000..7e1c7ae85e0 --- /dev/null +++ b/packages/react-charts/src/victory/components/Skeletons/examples/skeletons.md @@ -0,0 +1,126 @@ +--- +id: Skeletons +section: components +subsection: charts +propComponents: [ + 'Chart', + 'ChartArea', + 'ChartAxis', + 'ChartBar', + 'ChartBoxPlot', + 'ChartBullet', + 'ChartDonut', + 'ChartDonutThreshold', + 'ChartDonutUtilization', + 'ChartLegend', + 'ChartLine', + 'ChartGroup', + 'ChartPie', + 'ChartScatter', + 'ChartStack', + 'ChartThreshold', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { useState } from 'react'; +import { Chart, ChartArea, ChartAxis, ChartBar, ChartBoxPlot, ChartBullet, ChartDonut, ChartDonutThreshold, ChartDonutUtilization, ChartLegend, ChartLine, ChartGroup, ChartPie, ChartScatter, ChartStack, ChartThemeColor, ChartThreshold, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Area chart +```ts file = "SkeletonsAreaChart.tsx" + +``` + +### Bar chart +```ts file = "SkeletonsBarChart.tsx" + +``` + +### Box plot chart +```ts file = "SkeletonsBoxPlotChart.tsx" + +``` + +### Bullet chart +```ts file = "SkeletonsBulletChart.tsx" + +``` + +### Donut chart +```ts file = "SkeletonsDonutChart.tsx" + +``` + +### Donut utilization chart +```ts file = "SkeletonsDonutUtilizationChart.tsx" + +``` + +### Donut utilization threshold +```ts file = "SkeletonsDonutUtilizationThreshold.tsx" + +``` + +### Line chart +```ts file = "SkeletonsLineChart.tsx" + +``` + +### Pie chart +```ts file = "SkeletonsPieChart.tsx" + +``` + +### Scatter chart +```ts file = "SkeletonsScatterChart.tsx" + +``` + +### Stack chart +```ts file = "SkeletonsStackChart.tsx" + +``` + +### Threshold chart +```ts file = "SkeletonsThresholdChart.tsx" + +``` + +## Documentation +### Tips +- It's best for skeletons not to include interactions such as tooltips, cursors, interactive legends, etc. +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- `ChartLegend` may be used as a standalone component, instead of using `legendData` +- The `theme` and `themeColor` props should be applied at the most top level component +- Use `ChartGroup` to apply theme color scales and other properties to multiple components + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart) +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis) +- For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartBoxPlot` props, see [VictoryBoxPlot](https://formidable.com/open-source/victory/docs/victory-box-plot) +- For `ChartBullet` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar) +- For `ChartDonut` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartDonutThreshold` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartDonutUtilization` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartLine` props, see [Victoryline](https://formidable.com/open-source/victory/docs/victory-line) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartPie` props, see [VictoryPie](https://formidable.com/open-source/victory/docs/victory-pie) +- For `ChartScatter` props, see [VictoryScatter](https://formidable.com/open-source/victory/docs/victory-scatter) +- For `ChartStack` props, see [VictoryStack](https://formidable.com/open-source/victory/docs/victory-stack) +- For `ChartThreshold` props, see [VictoryLine](https://formidable.com/open-source/victory/docs/victory-line) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/Sparkline/examples/SparklineBasic.tsx b/packages/react-charts/src/victory/components/Sparkline/examples/SparklineBasic.tsx new file mode 100644 index 00000000000..ab40f027cff --- /dev/null +++ b/packages/react-charts/src/victory/components/Sparkline/examples/SparklineBasic.tsx @@ -0,0 +1,46 @@ +import { + ChartArea, + ChartContainer, + ChartGroup, + ChartLabel, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const SparklineBasic: React.FunctionComponent = () => { + const data: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + + return ( +
    +
    + `${datum.name}: ${datum.y}`} constrainToVisibleArea /> + } + height={100} + maxDomain={{ y: 9 }} + name="chart1" + padding={0} + width={400} + > + + +
    + + + +
    + ); +}; diff --git a/packages/react-charts/src/victory/components/Sparkline/examples/SparklineGreen.tsx b/packages/react-charts/src/victory/components/Sparkline/examples/SparklineGreen.tsx new file mode 100644 index 00000000000..f5ba9ec5ac1 --- /dev/null +++ b/packages/react-charts/src/victory/components/Sparkline/examples/SparklineGreen.tsx @@ -0,0 +1,62 @@ +import { + ChartArea, + ChartContainer, + ChartGroup, + ChartLabel, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; +import { useEffect } from 'react'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const SparklineGreen: React.FunctionComponent = () => { + const data: PetData[] = [ + { name: 'Cats', x: '2015', y: 3 }, + { name: 'Cats', x: '2016', y: 4 }, + { name: 'Cats', x: '2017', y: 8 }, + { name: 'Cats', x: '2018', y: 6 } + ]; + + useEffect(() => { + // Workaround for documentation-framework issue https://github.com/patternfly/patternfly-react/issues/11455 + const sheet = (() => { + const style = document.createElement('style'); + document.head.appendChild(style); + return style.sheet; + })(); + + sheet.insertRule( + '.ws-react-charts-sparkline-overflow { margin-left: 50px; margin-top: 50px; height: 135px; }', + sheet.cssRules.length + ); + sheet.insertRule('.ws-react-charts-sparkline-overflow svg { overflow: visible; }', sheet.cssRules.length); + }, []); + + return ( +
    +
    + `${datum.name}: ${datum.y}`} />} + height={100} + maxDomain={{ y: 9 }} + name="chart2" + padding={0} + themeColor={ChartThemeColor.green} + width={400} + > + + +
    + + + +
    + ); +}; diff --git a/packages/react-charts/src/components/Sparkline/examples/sparkline.css b/packages/react-charts/src/victory/components/Sparkline/examples/sparkline.css similarity index 100% rename from packages/react-charts/src/components/Sparkline/examples/sparkline.css rename to packages/react-charts/src/victory/components/Sparkline/examples/sparkline.css diff --git a/packages/react-charts/src/victory/components/Sparkline/examples/sparkline.md b/packages/react-charts/src/victory/components/Sparkline/examples/sparkline.md new file mode 100644 index 00000000000..6802cb6bde0 --- /dev/null +++ b/packages/react-charts/src/victory/components/Sparkline/examples/sparkline.md @@ -0,0 +1,56 @@ +--- +id: Sparkline chart +section: components +subsection: charts +propComponents: [ + 'ChartArea', + 'ChartContainer', + 'ChartGroup', + 'ChartLabel', + 'ChartVoronoiContainer' +] +hideDarkMode: true +--- + +import { ChartArea, ChartContainer, ChartGroup, ChartLabel, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; +import { useEffect } from 'react'; + + + +## Introduction +Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! + +The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior. + +## Examples +### Basic +```ts file = "SparklineBasic.tsx" + +``` + +### Green + +This demonstrates an alternate way of applying tooltips using CSS overflow + +```ts file = "SparklineGreen.tsx" + +``` + +## Documentation +### Tips +- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq) +- For single data points or zero values, you may want to set the `domain` prop +- Use `ChartGroup` in place of `Chart` when an axis and labels are not desired +- Themes are inherited, so a default theme may override `themeColor` for a child component +- The `theme` and `themeColor` props should be applied at the most top level component + +### Note +Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the +components used in the examples above, Victory pass-thru props are also documented here: + +- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area) +- For `ChartGroup` props, see [VictoryGroup](https://formidable.com/open-source/victory/docs/victory-group) +- For `ChartLabel` props, see [VictoryLabel](https://formidable.com/open-source/victory/docs/victory-label) +- For `ChartVoronoiContainer` props, see [VictoryVoronoiContainer](https://formidable.com/open-source/victory/docs/victory-voronoi-container) diff --git a/packages/react-charts/src/victory/components/index.ts b/packages/react-charts/src/victory/components/index.ts new file mode 100644 index 00000000000..1536abdae83 --- /dev/null +++ b/packages/react-charts/src/victory/components/index.ts @@ -0,0 +1,40 @@ +/** Keep alphabetically sorted */ +export * from './Chart/Chart'; +export * from './ChartArea/ChartArea'; +export * from './ChartAxis/ChartAxis'; +export * from './ChartBar/ChartBar'; +export * from './ChartBoxPlot/ChartBoxPlot'; +export * from './ChartBullet/ChartBullet'; +export * from './ChartBullet/ChartBulletComparativeErrorMeasure'; +export * from './ChartBullet/ChartBulletComparativeMeasure'; +export * from './ChartBullet/ChartBulletComparativeWarningMeasure'; +export * from './ChartBullet/ChartBulletPrimaryDotMeasure'; +export * from './ChartBullet/ChartBulletPrimarySegmentedMeasure'; +export * from './ChartBullet/ChartBulletQualitativeRange'; +export * from './ChartContainer/ChartContainer'; +export * from './ChartCursorContainer/ChartCursorContainer'; +export * from './ChartCursorTooltip/ChartCursorTooltip'; +export * from './ChartCursorTooltip/ChartCursorFlyout'; +export * from './ChartDonut/ChartDonut'; +export * from './ChartDonutUtilization/ChartDonutThreshold'; +export * from './ChartDonutUtilization/ChartDonutUtilization'; +export * from './ChartGroup/ChartGroup'; +export * from './ChartLabel/ChartLabel'; +export * from './ChartLegend/ChartLegend'; +export * from './ChartLegendTooltip/ChartLegendTooltip'; +export * from './ChartLegendTooltip/ChartLegendTooltipContent'; +export * from './ChartLegendTooltip/ChartLegendTooltipLabel'; +export * from './ChartLine/ChartLine'; +export * from './ChartPie/ChartPie'; +export * from './ChartPoint/ChartPoint'; +export * from './ChartScatter/ChartScatter'; +export * from './ChartStack/ChartStack'; +export * from './ChartTheme/ChartTheme'; +export * from './ChartTheme/ChartThemeColor'; +export * from './ChartThreshold/ChartThreshold'; +export * from './ChartTooltip/ChartTooltip'; +export * from './ChartVoronoiContainer/ChartVoronoiContainer'; + +export { createContainer } from './ChartUtils/chart-container'; +export { getInteractiveLegendEvents, getInteractiveLegendItemStyles } from './ChartUtils/chart-interactive-legend'; +export { getCustomTheme, getTheme, getThemeColors } from './ChartUtils/chart-theme'; diff --git a/packages/react-charts/src/index.ts b/packages/react-charts/src/victory/index.ts similarity index 100% rename from packages/react-charts/src/index.ts rename to packages/react-charts/src/victory/index.ts diff --git a/packages/react-charts/src/typings/hoist.d.ts b/packages/react-charts/src/victory/typings/hoist.d.ts similarity index 100% rename from packages/react-charts/src/typings/hoist.d.ts rename to packages/react-charts/src/victory/typings/hoist.d.ts diff --git a/packages/react-charts/src/typings/victory.d.ts b/packages/react-charts/src/victory/typings/victory.d.ts similarity index 100% rename from packages/react-charts/src/typings/victory.d.ts rename to packages/react-charts/src/victory/typings/victory.d.ts diff --git a/packages/react-charts/subpaths.config.json b/packages/react-charts/subpaths.config.json new file mode 100644 index 00000000000..706c0581100 --- /dev/null +++ b/packages/react-charts/subpaths.config.json @@ -0,0 +1,4 @@ +{ + "packageName": "@patternfly/react-charts", + "paths": ["echarts", "victory"] +} diff --git a/packages/react-charts/tsconfig.json b/packages/react-charts/tsconfig.json index 30bec2faa4a..b163d5d03bf 100644 --- a/packages/react-charts/tsconfig.json +++ b/packages/react-charts/tsconfig.json @@ -3,7 +3,12 @@ "compilerOptions": { "rootDir": "./src", "outDir": "./dist/esm", - "tsBuildInfoFile": "dist/esm.tsbuildinfo" + "tsBuildInfoFile": "dist/esm.tsbuildinfo", + "noImplicitAny": false, + "baseUrl": ".", + "paths": { + "./next": ["./src/echarts/next"] + } }, "include": [ "./src/*", diff --git a/packages/react-code-editor/CHANGELOG.md b/packages/react-code-editor/CHANGELOG.md index 4d358af5c7d..f88ec6da220 100644 --- a/packages/react-code-editor/CHANGELOG.md +++ b/packages/react-code-editor/CHANGELOG.md @@ -3,2846 +3,3051 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. -# 4.29.0 (2022-01-14) - - -### Features - -* **DescriptionList:** add option to fill columns first ([#6736](https://github.com/patternfly/patternfly-react/issues/6736)) ([c955c29](https://github.com/patternfly/patternfly-react/commit/c955c2917dbc4b85ce58fac4f93845c429186e1b)) - - +# [6.6.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.1-prerelease.0...@patternfly/react-code-editor@6.6.0-prerelease.1) (2026-05-26) +### Bug Fixes +- updated to do 6.6.0 prereleases. ([#12434](https://github.com/patternfly/patternfly-react/issues/12434)) ([6e09ce8](https://github.com/patternfly/patternfly-react/commit/6e09ce8322ff13354991d901782231d437249aa6)) -## 4.28.2 (2022-01-14) +## [6.5.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0...@patternfly/react-code-editor@6.5.1-prerelease.0) (2026-05-21) **Note:** Version bump only for package @patternfly/react-code-editor +# 6.5.0 (2026-05-20) +### Reverts +- Revert "chore(release): releasing packages [ci skip]" ([7185856](https://github.com/patternfly/patternfly-react/commit/7185856d4985da5129bbabd6c460049e7048dd2a)) - -## 4.28.1 (2022-01-14) +# [6.5.0-prerelease.82](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.81...@patternfly/react-code-editor@6.5.0-prerelease.82) (2026-05-19) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -# 4.28.0 (2022-01-12) - - -### Features - -* **expandable-section:** added indented variation ([#6763](https://github.com/patternfly/patternfly-react/issues/6763)) ([703b922](https://github.com/patternfly/patternfly-react/commit/703b9224e43bedd5b37ec41d8f26f2939836d610)) - - - - - -## 4.27.1 (2022-01-11) - - -### Bug Fixes - -* **Select:** update typeahead Select children when any option attribute changes ([#6747](https://github.com/patternfly/patternfly-react/issues/6747)) ([1e03f3c](https://github.com/patternfly/patternfly-react/commit/1e03f3c6d0a7c507e33398c98863e40bb2233a62)) - - - - - -# 4.27.0 (2022-01-11) - - -### Features - -* **ToggleGroup:** support disabling all items under the parent ([#6700](https://github.com/patternfly/patternfly-react/issues/6700)) ([a60c8f3](https://github.com/patternfly/patternfly-react/commit/a60c8f3485546c797750451714a70b7e84a4ba0f)) - - - - - -## 4.26.1 (2022-01-11) +# [6.5.0-prerelease.81](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.80...@patternfly/react-code-editor@6.5.0-prerelease.81) (2026-05-14) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -# 4.26.0 (2022-01-11) - - -### Features - -* **Table:** update clickable area for checks/radios ([#6754](https://github.com/patternfly/patternfly-react/issues/6754)) ([c4f3c2d](https://github.com/patternfly/patternfly-react/commit/c4f3c2d7f515e3d6ad73d8b52238ca426281469a)) - - - - - -## 4.25.2 (2022-01-10) +# [6.5.0-prerelease.80](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.79...@patternfly/react-code-editor@6.5.0-prerelease.80) (2026-05-13) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.25.1 (2022-01-10) +# [6.5.0-prerelease.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.78...@patternfly/react-code-editor@6.5.0-prerelease.79) (2026-05-12) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -# 4.25.0 (2022-01-10) - - -### Features - -* **Dropdown:** add plain-text variant support ([#6721](https://github.com/patternfly/patternfly-react/issues/6721)) ([e5000e3](https://github.com/patternfly/patternfly-react/commit/e5000e36194e36b9c6ae49efdb0a513125efcb70)) - - - - - -## 4.24.11 (2022-01-10) +# [6.5.0-prerelease.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.77...@patternfly/react-code-editor@6.5.0-prerelease.78) (2026-05-12) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.24.10 (2022-01-10) - - -### Bug Fixes - -* **Tabs:** allow href navigation from tabs ([#6755](https://github.com/patternfly/patternfly-react/issues/6755)) ([290d89a](https://github.com/patternfly/patternfly-react/commit/290d89aed2dd4517db9859cc80ef2745cb8a779b)) - - - - - -## 4.24.9 (2022-01-10) +# [6.5.0-prerelease.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.76...@patternfly/react-code-editor@6.5.0-prerelease.77) (2026-05-08) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.24.8 (2022-01-07) +# [6.5.0-prerelease.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.75...@patternfly/react-code-editor@6.5.0-prerelease.76) (2026-05-08) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.24.7 (2022-01-07) +# [6.5.0-prerelease.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.74...@patternfly/react-code-editor@6.5.0-prerelease.75) (2026-05-08) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.24.6 (2022-01-07) +# [6.5.0-prerelease.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.73...@patternfly/react-code-editor@6.5.0-prerelease.74) (2026-05-07) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.24.5 (2022-01-07) - - -### Bug Fixes - -* **jumplinks:** Updated JumpLinks demo to allow for horizontal display ([#6731](https://github.com/patternfly/patternfly-react/issues/6731)) ([f37b934](https://github.com/patternfly/patternfly-react/commit/f37b9342e678da247056c73767d5d40ff5435bda)) - - - - - -## 4.24.4 (2022-01-06) +# [6.5.0-prerelease.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.72...@patternfly/react-code-editor@6.5.0-prerelease.73) (2026-05-07) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.24.3 (2022-01-06) - - -### Bug Fixes - -* **TopologyControlBar:** Update screen reader className to latest ([#6739](https://github.com/patternfly/patternfly-react/issues/6739)) ([ed9da57](https://github.com/patternfly/patternfly-react/commit/ed9da575fddf9fe7af8a891972f7a66520785411)) - - - - - -## 4.24.2 (2022-01-06) +# [6.5.0-prerelease.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.71...@patternfly/react-code-editor@6.5.0-prerelease.72) (2026-05-07) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.24.1 (2022-01-06) +# [6.5.0-prerelease.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.70...@patternfly/react-code-editor@6.5.0-prerelease.71) (2026-05-05) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -# 4.24.0 (2022-01-05) - - -### Features - -* **Table:** allow a generic to be passed for cell props ([#6691](https://github.com/patternfly/patternfly-react/issues/6691)) ([e22c7be](https://github.com/patternfly/patternfly-react/commit/e22c7bebf630b7cd71e4dc434c593b69fa2fb2c8)) - - - - - -## 4.23.3 (2022-01-04) - - -### Bug Fixes - -* **docs:** fix broken theme-patternfly-org link ([#6726](https://github.com/patternfly/patternfly-react/issues/6726)) ([4ba15e9](https://github.com/patternfly/patternfly-react/commit/4ba15e9d9611afbb80d995e4d63f5478c4212a9e)) - - - - - -## 4.23.2 (2022-01-04) +# [6.5.0-prerelease.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.69...@patternfly/react-code-editor@6.5.0-prerelease.70) (2026-05-05) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.23.1 (2022-01-04) - - -### Bug Fixes - -* **OverflowMenu:** pass HTMLDivElements props to group and control divs ([#6674](https://github.com/patternfly/patternfly-react/issues/6674)) ([e6d0d64](https://github.com/patternfly/patternfly-react/commit/e6d0d6406a07de04f4b232ca9a21247c0e9746c0)) - - - - - -# 4.23.0 (2021-12-22) - - -### Features - -* **Toolbar:** support customizing text in ToolbarChipGroupContent ([#6694](https://github.com/patternfly/patternfly-react/issues/6694)) ([24266ad](https://github.com/patternfly/patternfly-react/commit/24266adf569c027574abd1503b5e46974220349a)) - - - - - -## 4.22.5 (2021-12-16) - - -### Bug Fixes - -* **LogViewer:** fix the issue that scrollbar could compress the content of the logs ([#6702](https://github.com/patternfly/patternfly-react/issues/6702)) ([11aab1f](https://github.com/patternfly/patternfly-react/commit/11aab1f71a1aa9959cf14b887ab55b845a794a00)) - - - - - -## 4.22.4 (2021-12-14) +# [6.5.0-prerelease.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.68...@patternfly/react-code-editor@6.5.0-prerelease.69) (2026-05-05) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.22.3 (2021-12-13) +# [6.5.0-prerelease.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.67...@patternfly/react-code-editor@6.5.0-prerelease.68) (2026-05-01) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.22.2 (2021-12-13) +# [6.5.0-prerelease.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.66...@patternfly/react-code-editor@6.5.0-prerelease.67) (2026-04-29) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.65...@patternfly/react-code-editor@6.5.0-prerelease.66) (2026-04-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.64...@patternfly/react-code-editor@6.5.0-prerelease.65) (2026-04-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## 4.22.1 (2021-12-09) +# [6.5.0-prerelease.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.63...@patternfly/react-code-editor@6.5.0-prerelease.64) (2026-04-24) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.62...@patternfly/react-code-editor@6.5.0-prerelease.63) (2026-04-24) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.61...@patternfly/react-code-editor@6.5.0-prerelease.62) (2026-04-20) +**Note:** Version bump only for package @patternfly/react-code-editor -# 4.22.0 (2021-12-09) +# [6.5.0-prerelease.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.60...@patternfly/react-code-editor@6.5.0-prerelease.61) (2026-04-17) +**Note:** Version bump only for package @patternfly/react-code-editor -### Features +# [6.5.0-prerelease.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.59...@patternfly/react-code-editor@6.5.0-prerelease.60) (2026-04-16) -* **Popover:** add composable header and alert variants ([#6664](https://github.com/patternfly/patternfly-react/issues/6664)) ([9028e8b](https://github.com/patternfly/patternfly-react/commit/9028e8ba5d674bde6a7e29532f7926e200dd632a)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.58...@patternfly/react-code-editor@6.5.0-prerelease.59) (2026-04-15) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.57...@patternfly/react-code-editor@6.5.0-prerelease.58) (2026-04-15) +**Note:** Version bump only for package @patternfly/react-code-editor -## 4.21.1 (2021-12-08) +# [6.5.0-prerelease.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.56...@patternfly/react-code-editor@6.5.0-prerelease.57) (2026-04-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.55...@patternfly/react-code-editor@6.5.0-prerelease.56) (2026-04-13) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.54...@patternfly/react-code-editor@6.5.0-prerelease.55) (2026-04-13) +**Note:** Version bump only for package @patternfly/react-code-editor -# 4.21.0 (2021-12-08) - +# [6.5.0-prerelease.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.53...@patternfly/react-code-editor@6.5.0-prerelease.54) (2026-04-10) ### Features -* **DualListSelector:** add composable tree example ([#6652](https://github.com/patternfly/patternfly-react/issues/6652)) ([5fe977b](https://github.com/patternfly/patternfly-react/commit/5fe977becb5dea615724abf846f315e50931c188)) - - - +- **Icons:** updated cog icons to rh settings ([#12345](https://github.com/patternfly/patternfly-react/issues/12345)) ([190da46](https://github.com/patternfly/patternfly-react/commit/190da4621acef4edd1697bb8ebccfd02299ae870)) - -## 4.20.1 (2021-12-07) +# [6.5.0-prerelease.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.52...@patternfly/react-code-editor@6.5.0-prerelease.53) (2026-04-06) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.51...@patternfly/react-code-editor@6.5.0-prerelease.52) (2026-04-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.50...@patternfly/react-code-editor@6.5.0-prerelease.51) (2026-04-01) +**Note:** Version bump only for package @patternfly/react-code-editor -# 4.20.0 (2021-12-06) - - -### Features +# [6.5.0-prerelease.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.49...@patternfly/react-code-editor@6.5.0-prerelease.50) (2026-04-01) -* **Card:** Add disabled card and clean up props ([#6659](https://github.com/patternfly/patternfly-react/issues/6659)) ([86f225a](https://github.com/patternfly/patternfly-react/commit/86f225ab2e02d617e2d380c4a7f7593037c50e84)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.48...@patternfly/react-code-editor@6.5.0-prerelease.49) (2026-04-01) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.47...@patternfly/react-code-editor@6.5.0-prerelease.48) (2026-04-01) +**Note:** Version bump only for package @patternfly/react-code-editor -# 4.19.0 (2021-12-06) +# [6.5.0-prerelease.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.46...@patternfly/react-code-editor@6.5.0-prerelease.47) (2026-03-31) +**Note:** Version bump only for package @patternfly/react-code-editor -### Features +# [6.5.0-prerelease.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.45...@patternfly/react-code-editor@6.5.0-prerelease.46) (2026-03-31) -* **MenuToggle:** add plain with text variant ([#6627](https://github.com/patternfly/patternfly-react/issues/6627)) ([1f4ca5e](https://github.com/patternfly/patternfly-react/commit/1f4ca5e36d7077da3ff3e6918874048c784216e0)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.44...@patternfly/react-code-editor@6.5.0-prerelease.45) (2026-03-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.43...@patternfly/react-code-editor@6.5.0-prerelease.44) (2026-03-25) +**Note:** Version bump only for package @patternfly/react-code-editor -# 4.18.0 (2021-12-06) +# [6.5.0-prerelease.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.42...@patternfly/react-code-editor@6.5.0-prerelease.43) (2026-03-25) +**Note:** Version bump only for package @patternfly/react-code-editor -### Features +# [6.5.0-prerelease.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.41...@patternfly/react-code-editor@6.5.0-prerelease.42) (2026-03-19) -* **Dropdown:** add toggle variants ([#6651](https://github.com/patternfly/patternfly-react/issues/6651)) ([6414309](https://github.com/patternfly/patternfly-react/commit/64143094aec86aed86adb320e059d987af4f5f24)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.40...@patternfly/react-code-editor@6.5.0-prerelease.41) (2026-03-13) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.39...@patternfly/react-code-editor@6.5.0-prerelease.40) (2026-03-05) +**Note:** Version bump only for package @patternfly/react-code-editor -## 4.17.1 (2021-12-06) +# [6.5.0-prerelease.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.38...@patternfly/react-code-editor@6.5.0-prerelease.39) (2026-02-26) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.37...@patternfly/react-code-editor@6.5.0-prerelease.38) (2026-02-25) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.36...@patternfly/react-code-editor@6.5.0-prerelease.37) (2026-02-24) +**Note:** Version bump only for package @patternfly/react-code-editor -# 4.17.0 (2021-12-03) - +# [6.5.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.35...@patternfly/react-code-editor@6.5.0-prerelease.36) (2026-02-18) ### Features -* **Select:** add ability to persist filtered children state ([#6670](https://github.com/patternfly/patternfly-react/issues/6670)) ([f618577](https://github.com/patternfly/patternfly-react/commit/f618577582e389409978bd1d6512ca0cf5d855cf)) - - - - - -## 4.16.17 (2021-12-03) - - -### Bug Fixes - -* **Slider:** fixed examples with custom steps and input ([#6662](https://github.com/patternfly/patternfly-react/issues/6662)) ([b4cab38](https://github.com/patternfly/patternfly-react/commit/b4cab38a2492564bf91e3711ce322951bcc6a051)) - - +- **icons:** add swap support for mapped rh-ui icons ([#12245](https://github.com/patternfly/patternfly-react/issues/12245)) ([a81ce0e](https://github.com/patternfly/patternfly-react/commit/a81ce0e1b6fdd7a3e85cdd70e5bb667dc7d82801)) +# [6.5.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.34...@patternfly/react-code-editor@6.5.0-prerelease.35) (2026-02-06) +**Note:** Version bump only for package @patternfly/react-code-editor -## 4.16.16 (2021-12-02) +# [6.5.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.33...@patternfly/react-code-editor@6.5.0-prerelease.34) (2026-02-06) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.32...@patternfly/react-code-editor@6.5.0-prerelease.33) (2026-02-05) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.31...@patternfly/react-code-editor@6.5.0-prerelease.32) (2026-02-05) +**Note:** Version bump only for package @patternfly/react-code-editor -## 4.16.15 (2021-12-02) - +# [6.5.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.30...@patternfly/react-code-editor@6.5.0-prerelease.31) (2026-01-27) ### Bug Fixes -* **Tile:** fix selecting tile in tile demo ([#6653](https://github.com/patternfly/patternfly-react/issues/6653)) ([e12e44d](https://github.com/patternfly/patternfly-react/commit/e12e44d4b623de305b7df04174144a9496d282a7)) - - - +- **CodeEditor:** prevent focus loss ([#12211](https://github.com/patternfly/patternfly-react/issues/12211)) ([#12212](https://github.com/patternfly/patternfly-react/issues/12212)) ([61ea8ae](https://github.com/patternfly/patternfly-react/commit/61ea8aeb5e80229fcb7ce2f2b731b745b978fc19)) - -## 4.16.14 (2021-12-01) +# [6.5.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.29...@patternfly/react-code-editor@6.5.0-prerelease.30) (2026-01-12) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.16.13 (2021-11-30) +# [6.5.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.28...@patternfly/react-code-editor@6.5.0-prerelease.29) (2026-01-09) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.27...@patternfly/react-code-editor@6.5.0-prerelease.28) (2026-01-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.26...@patternfly/react-code-editor@6.5.0-prerelease.27) (2025-12-17) +**Note:** Version bump only for package @patternfly/react-code-editor -## 4.16.12 (2021-11-30) - - -### Bug Fixes - -* **action-list:** added support for classname ([#6647](https://github.com/patternfly/patternfly-react/issues/6647)) ([dd3d2ce](https://github.com/patternfly/patternfly-react/commit/dd3d2ce32b4d3e7562faf465abdc508e17f097d9)) - - - +# [6.5.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.22...@patternfly/react-code-editor@6.5.0-prerelease.26) (2025-12-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## 4.16.11 (2021-11-30) +# [6.5.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.21...@patternfly/react-code-editor@6.5.0-prerelease.22) (2025-12-03) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.16.10 (2021-11-23) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.16.9 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.16.8 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.16.7 (2021-11-18) - - -### Bug Fixes - -* **pagination:** updated toggleTemplate prop description to include ofWord prop ([#6622](https://github.com/patternfly/patternfly-react/issues/6622)) ([26733a6](https://github.com/patternfly/patternfly-react/commit/26733a6a256ad0e873afbc268a712027470fdeaa)) - - - - - -## 4.16.6 (2021-11-18) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.16.5 (2021-11-17) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.16.4 (2021-11-15) - - -### Bug Fixes - -* **FileUpload:** Downgrade react-dropzone back to 9.0.0 to avoid a breaking type change, fix behavior regressions ([#6610](https://github.com/patternfly/patternfly-react/issues/6610)) ([574bf4f](https://github.com/patternfly/patternfly-react/commit/574bf4ff3ccf7f67ce750bc48067eaf826e99990)) - - - - - -## 4.16.3 (2021-11-15) - - -### Bug Fixes - -* **Menu:** allow maxMenuHeight with Scrollabe ([#6608](https://github.com/patternfly/patternfly-react/issues/6608)) ([8c1f12c](https://github.com/patternfly/patternfly-react/commit/8c1f12c2b0e86bbc5ba1071db3ebf29fee7421a0)) - - - - - -## 4.16.2 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.16.1 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -# 4.16.0 (2021-11-12) - - -### Features - -* **card:** added hoverable/selectable/selected-raised variant ([#6565](https://github.com/patternfly/patternfly-react/issues/6565)) ([8c60568](https://github.com/patternfly/patternfly-react/commit/8c60568ba4fa18398fed636710e222ce506de82c)) - - - - - -## 4.15.2 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.15.1 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -# 4.15.0 (2021-11-11) - - -### Features - -* **ComposableTable:** add sticky columns and nested headers ([#6538](https://github.com/patternfly/patternfly-react/issues/6538)) ([f11245b](https://github.com/patternfly/patternfly-react/commit/f11245bfccc8c6c02a9d5545a69ed533743cc552)) - - - - - -# 4.14.0 (2021-11-11) - - -### Features - -* **contextselector:** added support for context selector items as links ([#6554](https://github.com/patternfly/patternfly-react/issues/6554)) ([c465388](https://github.com/patternfly/patternfly-react/commit/c4653881eee0cd8ec8e3a7125bbef0bded9f2de0)) - - - - - -# 4.13.0 (2021-11-11) - - -### Features - -* **Navigation:** Added exemple with third level ([#6564](https://github.com/patternfly/patternfly-react/issues/6564)) ([c30da53](https://github.com/patternfly/patternfly-react/commit/c30da532855118f705c8cfc87c545bb1eea11ebb)) - - - - - -# 4.12.0 (2021-11-11) - - -### Features - -* enhance type correctness of CodeEditor ([#6579](https://github.com/patternfly/patternfly-react/issues/6579)) ([e1ad65c](https://github.com/patternfly/patternfly-react/commit/e1ad65c225968d5a9c74019d19e4a3c5e2666926)) - - - - - -## 4.11.4 (2021-11-10) - - -### Bug Fixes - -* **jumplinks:** fixed to always set clicked item as active ([#6542](https://github.com/patternfly/patternfly-react/issues/6542)) ([845c98f](https://github.com/patternfly/patternfly-react/commit/845c98f5f3df8aa9b6acc190707c5f1d7bf3ca38)) - - - - - -## 4.11.3 (2021-11-10) - - -### Bug Fixes - -* **Menu:** stop passing disableHover to DrilldownMenu DOM ([#6571](https://github.com/patternfly/patternfly-react/issues/6571)) ([63dcf25](https://github.com/patternfly/patternfly-react/commit/63dcf256723848ff3789828fc0a5f86d5009fc87)) - - - - - -## 4.11.2 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.11.1 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -# 4.11.0 (2021-11-09) - - -### Features - -* **Table:** set default sort direction ([#6544](https://github.com/patternfly/patternfly-react/issues/6544)) ([9ee4942](https://github.com/patternfly/patternfly-react/commit/9ee49428c8e1041721f2a09f8176a5aba3335049)) - - - - - -## 4.10.4 (2021-11-09) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.10.3 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.10.2 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.10.1 (2021-11-08) - - -### Bug Fixes - -* **acccessconsoles:** use object type Select options values in order to not mix displayed text with option keys ([#6496](https://github.com/patternfly/patternfly-react/issues/6496)) ([975c8e1](https://github.com/patternfly/patternfly-react/commit/975c8e14d7ea8c53eb4048ea6ef73e804b3ad2be)) - - - - - -# 4.10.0 (2021-11-04) - - -### Features - -* **log-viewer:** support ANSI color ([#6519](https://github.com/patternfly/patternfly-react/issues/6519)) ([936a699](https://github.com/patternfly/patternfly-react/commit/936a699b0514a492d3c40be08932fb7bab275cce)) - - - - - -## 4.9.11 (2021-11-01) - - -### Bug Fixes - -* **AboutModal:** allow to disable FocusTrap ([#6509](https://github.com/patternfly/patternfly-react/issues/6509)) ([72536e1](https://github.com/patternfly/patternfly-react/commit/72536e1f73641ff3f19f865f08dbb41ad0ee7b9f)) - - - - - -## 4.9.10 (2021-10-29) - - -### Bug Fixes - -* **Banner:** forward props ([#6511](https://github.com/patternfly/patternfly-react/issues/6511)) ([e36c890](https://github.com/patternfly/patternfly-react/commit/e36c89077afa82340994c0e3c0fc929e601e01bc)) - - - - - -## 4.9.9 (2021-10-28) +# [6.5.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.20...@patternfly/react-code-editor@6.5.0-prerelease.21) (2025-12-03) **Note:** Version bump only for package @patternfly/react-code-editor - - - - -## 4.9.8 (2021-10-27) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.9.7 (2021-10-27) - - -### Bug Fixes - -* change transformer cjs package to private ([#6515](https://github.com/patternfly/patternfly-react/issues/6515)) ([efcb357](https://github.com/patternfly/patternfly-react/commit/efcb3573b71541328ce2b16caa80ce33b2a62131)) - - - - - -## 4.9.6 (2021-10-26) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.9.5 (2021-10-26) - - -### Bug Fixes - -* **tokens:** added check for no matching var to avoid infinite loop ([#6502](https://github.com/patternfly/patternfly-react/issues/6502)) ([99605c2](https://github.com/patternfly/patternfly-react/commit/99605c213f12490d0abe75910e05c3e6da26a1f3)) - - - - - -## 4.9.4 (2021-10-26) - - -### Bug Fixes - -* add transformer package ([#6507](https://github.com/patternfly/patternfly-react/issues/6507)) ([daffd28](https://github.com/patternfly/patternfly-react/commit/daffd2864388abe63e625f962a8b38c2b7056209)) - - - - - -## 4.9.3 (2021-10-26) - - -### Bug Fixes - -* **transformer:** publish transformer in patternfly org ([#6506](https://github.com/patternfly/patternfly-react/issues/6506)) ([b739af3](https://github.com/patternfly/patternfly-react/commit/b739af318400b41d4e9a53bdff6232ecc176916e)) - - - - - -## 4.9.2 (2021-10-26) - - -### Bug Fixes - -* **readme:** update react-core readme ([#6505](https://github.com/patternfly/patternfly-react/issues/6505)) ([d4f9a11](https://github.com/patternfly/patternfly-react/commit/d4f9a114584eea7ab67873f199e80b348886e14b)) - - - - - -## 4.9.1 (2021-10-26) - - -### Bug Fixes - -* **DualListSelector:** account for duplicate folders ([#6499](https://github.com/patternfly/patternfly-react/issues/6499)) ([e531e68](https://github.com/patternfly/patternfly-react/commit/e531e68e7adc58459b3630f5c915ed69e3021012)) - - - - - -# 4.9.0 (2021-10-26) - - -### Features - -* **toolbar:** add sticky top modifier to toolbar ([#6447](https://github.com/patternfly/patternfly-react/issues/6447)) ([fe7605a](https://github.com/patternfly/patternfly-react/commit/fe7605a67428b43ec00b3cb2117270296576737c)) - - - - - -## 4.8.1 (2021-10-26) - - -### Bug Fixes - -* **types:** SelectOptionProp made optional ([#6503](https://github.com/patternfly/patternfly-react/issues/6503)) ([716ac80](https://github.com/patternfly/patternfly-react/commit/716ac80e2414507d589ee3002fc0cea0068ae59c)) - - - - - -# 4.8.0 (2021-10-26) - - -### Features - -* **TextInputGroup:** add text input group ([#6482](https://github.com/patternfly/patternfly-react/issues/6482)) ([a02fd4f](https://github.com/patternfly/patternfly-react/commit/a02fd4fe3345245b2252ee5a261f5b1460490642)), closes [patternfly/patternfly-react#6409](https://github.com/patternfly/patternfly-react/issues/6409) - - - - - -## 4.7.4 (2021-10-26) - - -### Bug Fixes - -* **KebabToggle:** adds event to onToggle definition ([#6490](https://github.com/patternfly/patternfly-react/issues/6490)) ([0441575](https://github.com/patternfly/patternfly-react/commit/04415757917062aa13c06b34bd94ef38c2334088)) - - - - - -## 4.7.3 (2021-10-26) - - -### Bug Fixes - -* **Modal:** test clean up ([#6489](https://github.com/patternfly/patternfly-react/issues/6489)) ([c8eaa7c](https://github.com/patternfly/patternfly-react/commit/c8eaa7c838fbedb98ea0f38e4f535488040a72e2)) - - - - - -## 4.7.2 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.7.1 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -# 4.7.0 (2021-10-25) - - -### Features - -* **Tabs:** Added support for tab content body with padding, added tabs open and tab secondary tabs demos ([#6484](https://github.com/patternfly/patternfly-react/issues/6484)) ([0ccbe9d](https://github.com/patternfly/patternfly-react/commit/0ccbe9d1e6e0dac0730466c92a90fe2cd9f6560d)) - - - - - -## 4.6.1 (2021-10-21) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -# 4.6.0 (2021-10-21) - - -### Features - -* **label:** added compact label, updated horizontal grid card demo ([#6448](https://github.com/patternfly/patternfly-react/issues/6448)) ([89e0431](https://github.com/patternfly/patternfly-react/commit/89e04317924282140606d45f2292aa3f658b4b6c)) - - - - - -## 4.5.1 (2021-10-21) - - -### Bug Fixes - -* **DescriptionListGroup:** forward props to DOM ([#6466](https://github.com/patternfly/patternfly-react/issues/6466)) ([b78e2aa](https://github.com/patternfly/patternfly-react/commit/b78e2aa9c0360ce8418f6e7b55274ea1a50de518)) - - - - - -# 4.5.0 (2021-10-20) - - -### Features - -* **Progress:** allow node titles ([#6470](https://github.com/patternfly/patternfly-react/issues/6470)) ([46d5252](https://github.com/patternfly/patternfly-react/commit/46d52523ad5111bb11729c2750abe9aeb35d9326)) - - - - - -# 4.4.0 (2021-10-20) - - -### Features - -* **DualListSelector:** add disabled flag ([#6442](https://github.com/patternfly/patternfly-react/issues/6442)) ([85e1314](https://github.com/patternfly/patternfly-react/commit/85e131435be12c2df79336e9fa56987ed3717417)) - - - - - -## 4.3.90 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## 4.3.89 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## [4.3.88](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.87...@patternfly/react-code-editor@4.3.88) (2021-10-18) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## [4.3.87](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.86...@patternfly/react-code-editor@4.3.87) (2021-10-14) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## [4.3.86](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.85...@patternfly/react-code-editor@4.3.86) (2021-10-14) - -**Note:** Version bump only for package @patternfly/react-code-editor - - - - - -## [4.3.85](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.84...@patternfly/react-code-editor@4.3.85) (2021-10-13) +# [6.5.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.19...@patternfly/react-code-editor@6.5.0-prerelease.20) (2025-12-01) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.18...@patternfly/react-code-editor@6.5.0-prerelease.19) (2025-11-21) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.17...@patternfly/react-code-editor@6.5.0-prerelease.18) (2025-11-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.84](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.83...@patternfly/react-code-editor@4.3.84) (2021-10-11) +# [6.5.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.16...@patternfly/react-code-editor@6.5.0-prerelease.17) (2025-11-20) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.15...@patternfly/react-code-editor@6.5.0-prerelease.16) (2025-11-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.14...@patternfly/react-code-editor@6.5.0-prerelease.15) (2025-11-19) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.83](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.82...@patternfly/react-code-editor@4.3.83) (2021-10-11) +# [6.5.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.13...@patternfly/react-code-editor@6.5.0-prerelease.14) (2025-11-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.12...@patternfly/react-code-editor@6.5.0-prerelease.13) (2025-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.11...@patternfly/react-code-editor@6.5.0-prerelease.12) (2025-11-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.82](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.81...@patternfly/react-code-editor@4.3.82) (2021-10-11) +# [6.5.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.10...@patternfly/react-code-editor@6.5.0-prerelease.11) (2025-11-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.9...@patternfly/react-code-editor@6.5.0-prerelease.10) (2025-11-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.8...@patternfly/react-code-editor@6.5.0-prerelease.9) (2025-11-06) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.81](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.80...@patternfly/react-code-editor@4.3.81) (2021-10-11) +# [6.5.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.7...@patternfly/react-code-editor@6.5.0-prerelease.8) (2025-11-06) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.6...@patternfly/react-code-editor@6.5.0-prerelease.7) (2025-11-05) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.5...@patternfly/react-code-editor@6.5.0-prerelease.6) (2025-11-05) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.80](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.79...@patternfly/react-code-editor@4.3.80) (2021-10-08) +# [6.5.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.4...@patternfly/react-code-editor@6.5.0-prerelease.5) (2025-11-05) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.3...@patternfly/react-code-editor@6.5.0-prerelease.4) (2025-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.2...@patternfly/react-code-editor@6.5.0-prerelease.3) (2025-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.78...@patternfly/react-code-editor@4.3.79) (2021-10-07) +# [6.5.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.5.0-prerelease.1...@patternfly/react-code-editor@6.5.0-prerelease.2) (2025-10-31) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.5.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.9...@patternfly/react-code-editor@6.5.0-prerelease.1) (2025-10-30) +### Bug Fixes + +- **deps:** update dependency @monaco-editor/react to ^4.7.0 ([#11527](https://github.com/patternfly/patternfly-react/issues/11527)) ([c1581d5](https://github.com/patternfly/patternfly-react/commit/c1581d59e4f8a969726dae6383582a5e0aa48152)) +## [6.4.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.8...@patternfly/react-code-editor@6.4.1-prerelease.9) (2025-10-24) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.77...@patternfly/react-code-editor@4.3.78) (2021-10-07) +## [6.4.1-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.7...@patternfly/react-code-editor@6.4.1-prerelease.8) (2025-10-23) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.4.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.6...@patternfly/react-code-editor@6.4.1-prerelease.7) (2025-10-23) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.4.1-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.5...@patternfly/react-code-editor@6.4.1-prerelease.6) (2025-10-23) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.76...@patternfly/react-code-editor@4.3.77) (2021-10-06) +## [6.4.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.4...@patternfly/react-code-editor@6.4.1-prerelease.5) (2025-10-23) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.4.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.3...@patternfly/react-code-editor@6.4.1-prerelease.4) (2025-10-23) + +### Bug Fixes +- **CodeEditorControl:** make icon prop optional ([#12068](https://github.com/patternfly/patternfly-react/issues/12068)) ([bbb502a](https://github.com/patternfly/patternfly-react/commit/bbb502a04e5e7d5dda798ff0afec75db0d8fc689)), closes [#12065](https://github.com/patternfly/patternfly-react/issues/12065) +## [6.4.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.2...@patternfly/react-code-editor@6.4.1-prerelease.3) (2025-10-23) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.75...@patternfly/react-code-editor@4.3.76) (2021-10-06) +## [6.4.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.1...@patternfly/react-code-editor@6.4.1-prerelease.2) (2025-10-22) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.4.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.1-prerelease.0...@patternfly/react-code-editor@6.4.1-prerelease.1) (2025-10-21) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.4.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.0...@patternfly/react-code-editor@6.4.1-prerelease.0) (2025-10-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.74...@patternfly/react-code-editor@4.3.75) (2021-10-06) +# [6.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.0-prerelease.5...@patternfly/react-code-editor@6.4.0) (2025-10-16) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.4.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.0-prerelease.4...@patternfly/react-code-editor@6.4.0-prerelease.5) (2025-10-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.4.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.0-prerelease.3...@patternfly/react-code-editor@6.4.0-prerelease.4) (2025-10-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.73...@patternfly/react-code-editor@4.3.74) (2021-10-05) +# [6.4.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.0-prerelease.2...@patternfly/react-code-editor@6.4.0-prerelease.3) (2025-10-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.4.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.0-prerelease.1...@patternfly/react-code-editor@6.4.0-prerelease.2) (2025-10-01) +**Note:** Version bump only for package @patternfly/react-code-editor + +# [6.4.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.22...@patternfly/react-code-editor@6.4.0-prerelease.1) (2025-09-26) +### Bug Fixes +- updated to 6.4.0-prerelease ([df46ac6](https://github.com/patternfly/patternfly-react/commit/df46ac6bed381eb3e01e5573f77d79301b02b7fa)) -## [4.3.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.72...@patternfly/react-code-editor@4.3.73) (2021-10-05) +## [6.3.1-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.21...@patternfly/react-code-editor@6.3.1-prerelease.22) (2025-09-26) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.20...@patternfly/react-code-editor@6.3.1-prerelease.21) (2025-09-25) +### Features +- **CodeEditor:** use custom PatternFly monaco theme ([#11785](https://github.com/patternfly/patternfly-react/issues/11785)) ([eed7e65](https://github.com/patternfly/patternfly-react/commit/eed7e6528babba9c7c9bb6e8cb75186e984eac71)) - -## [4.3.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.71...@patternfly/react-code-editor@4.3.72) (2021-10-05) +## [6.3.1-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.19...@patternfly/react-code-editor@6.3.1-prerelease.20) (2025-09-25) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.18...@patternfly/react-code-editor@6.3.1-prerelease.19) (2025-09-24) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.17...@patternfly/react-code-editor@6.3.1-prerelease.18) (2025-09-24) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.70...@patternfly/react-code-editor@4.3.71) (2021-10-05) +## [6.3.1-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.16...@patternfly/react-code-editor@6.3.1-prerelease.17) (2025-09-24) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.15...@patternfly/react-code-editor@6.3.1-prerelease.16) (2025-09-24) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.14...@patternfly/react-code-editor@6.3.1-prerelease.15) (2025-09-23) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.69...@patternfly/react-code-editor@4.3.70) (2021-10-01) +## [6.3.1-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.13...@patternfly/react-code-editor@6.3.1-prerelease.14) (2025-09-11) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.12...@patternfly/react-code-editor@6.3.1-prerelease.13) (2025-09-11) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.11...@patternfly/react-code-editor@6.3.1-prerelease.12) (2025-09-10) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.68...@patternfly/react-code-editor@4.3.69) (2021-10-01) +## [6.3.1-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.10...@patternfly/react-code-editor@6.3.1-prerelease.11) (2025-09-10) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.9...@patternfly/react-code-editor@6.3.1-prerelease.10) (2025-09-10) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.8...@patternfly/react-code-editor@6.3.1-prerelease.9) (2025-09-09) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.67...@patternfly/react-code-editor@4.3.68) (2021-09-30) +## [6.3.1-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.7...@patternfly/react-code-editor@6.3.1-prerelease.8) (2025-09-05) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.6...@patternfly/react-code-editor@6.3.1-prerelease.7) (2025-08-26) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.5...@patternfly/react-code-editor@6.3.1-prerelease.6) (2025-08-18) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.66...@patternfly/react-code-editor@4.3.67) (2021-09-29) +## [6.3.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.4...@patternfly/react-code-editor@6.3.1-prerelease.5) (2025-08-18) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.3...@patternfly/react-code-editor@6.3.1-prerelease.4) (2025-08-12) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.2...@patternfly/react-code-editor@6.3.1-prerelease.3) (2025-08-05) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.65...@patternfly/react-code-editor@4.3.66) (2021-09-27) +## [6.3.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.1...@patternfly/react-code-editor@6.3.1-prerelease.2) (2025-08-05) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.1-prerelease.0...@patternfly/react-code-editor@6.3.1-prerelease.1) (2025-08-04) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.3.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0...@patternfly/react-code-editor@6.3.1-prerelease.0) (2025-07-28) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.64...@patternfly/react-code-editor@4.3.65) (2021-09-27) +# 6.3.0 (2025-07-22) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.4.0-prerelease.0...@patternfly/react-code-editor@6.3.0-prerelease.34) (2025-07-22) +### Reverts +- Revert "chore(release): releasing packages [ci skip]" ([40999d7](https://github.com/patternfly/patternfly-react/commit/40999d70a7a3aeadbe8f40fe96bb01ab3a6219d4)) - -## [4.3.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.63...@patternfly/react-code-editor@4.3.64) (2021-09-24) +# [6.3.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.32...@patternfly/react-code-editor@6.3.0-prerelease.33) (2025-07-18) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.31...@patternfly/react-code-editor@6.3.0-prerelease.32) (2025-07-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.30...@patternfly/react-code-editor@6.3.0-prerelease.31) (2025-07-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.62...@patternfly/react-code-editor@4.3.63) (2021-09-22) +# [6.3.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.29...@patternfly/react-code-editor@6.3.0-prerelease.30) (2025-07-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.28...@patternfly/react-code-editor@6.3.0-prerelease.29) (2025-07-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.27...@patternfly/react-code-editor@6.3.0-prerelease.28) (2025-07-01) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.61...@patternfly/react-code-editor@4.3.62) (2021-09-20) +# [6.3.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.26...@patternfly/react-code-editor@6.3.0-prerelease.27) (2025-06-23) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.25...@patternfly/react-code-editor@6.3.0-prerelease.26) (2025-06-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.24...@patternfly/react-code-editor@6.3.0-prerelease.25) (2025-06-18) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.60...@patternfly/react-code-editor@4.3.61) (2021-09-18) +# [6.3.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.23...@patternfly/react-code-editor@6.3.0-prerelease.24) (2025-06-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.22...@patternfly/react-code-editor@6.3.0-prerelease.23) (2025-06-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.21...@patternfly/react-code-editor@6.3.0-prerelease.22) (2025-06-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.59...@patternfly/react-code-editor@4.3.60) (2021-09-16) +# [6.3.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.20...@patternfly/react-code-editor@6.3.0-prerelease.21) (2025-06-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.19...@patternfly/react-code-editor@6.3.0-prerelease.20) (2025-06-13) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.18...@patternfly/react-code-editor@6.3.0-prerelease.19) (2025-06-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.58...@patternfly/react-code-editor@4.3.59) (2021-09-14) +# [6.3.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.17...@patternfly/react-code-editor@6.3.0-prerelease.18) (2025-06-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.16...@patternfly/react-code-editor@6.3.0-prerelease.17) (2025-06-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.15...@patternfly/react-code-editor@6.3.0-prerelease.16) (2025-05-29) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.57...@patternfly/react-code-editor@4.3.58) (2021-09-14) +# [6.3.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.14...@patternfly/react-code-editor@6.3.0-prerelease.15) (2025-05-29) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.13...@patternfly/react-code-editor@6.3.0-prerelease.14) (2025-05-21) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.12...@patternfly/react-code-editor@6.3.0-prerelease.13) (2025-05-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.56...@patternfly/react-code-editor@4.3.57) (2021-09-14) +# [6.3.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.11...@patternfly/react-code-editor@6.3.0-prerelease.12) (2025-05-20) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.10...@patternfly/react-code-editor@6.3.0-prerelease.11) (2025-05-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.9...@patternfly/react-code-editor@6.3.0-prerelease.10) (2025-05-15) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.55...@patternfly/react-code-editor@4.3.56) (2021-09-13) +# [6.3.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.8...@patternfly/react-code-editor@6.3.0-prerelease.9) (2025-05-15) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.7...@patternfly/react-code-editor@6.3.0-prerelease.8) (2025-05-13) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.6...@patternfly/react-code-editor@6.3.0-prerelease.7) (2025-05-07) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.54...@patternfly/react-code-editor@4.3.55) (2021-09-13) +# [6.3.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.5...@patternfly/react-code-editor@6.3.0-prerelease.6) (2025-05-07) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.4...@patternfly/react-code-editor@6.3.0-prerelease.5) (2025-05-07) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.3...@patternfly/react-code-editor@6.3.0-prerelease.4) (2025-04-30) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.53...@patternfly/react-code-editor@4.3.54) (2021-09-13) +# [6.3.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.2...@patternfly/react-code-editor@6.3.0-prerelease.3) (2025-04-30) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.3.0-prerelease.1...@patternfly/react-code-editor@6.3.0-prerelease.2) (2025-04-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.3.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.14...@patternfly/react-code-editor@6.3.0-prerelease.1) (2025-04-24) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.52...@patternfly/react-code-editor@4.3.53) (2021-09-13) +## [6.2.1-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.13...@patternfly/react-code-editor@6.2.1-prerelease.14) (2025-04-23) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.12...@patternfly/react-code-editor@6.2.1-prerelease.13) (2025-04-22) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.11...@patternfly/react-code-editor@6.2.1-prerelease.12) (2025-04-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.51...@patternfly/react-code-editor@4.3.52) (2021-09-13) +## [6.2.1-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.10...@patternfly/react-code-editor@6.2.1-prerelease.11) (2025-04-21) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.9...@patternfly/react-code-editor@6.2.1-prerelease.10) (2025-04-21) +### Features + +- **version:** testing react 19 ([#11754](https://github.com/patternfly/patternfly-react/issues/11754)) ([b981588](https://github.com/patternfly/patternfly-react/commit/b9815886da3adc7a96bc2d48adacf86e8a752e61)) +## [6.2.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.8...@patternfly/react-code-editor@6.2.1-prerelease.9) (2025-04-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.50...@patternfly/react-code-editor@4.3.51) (2021-09-13) +## [6.2.1-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.7...@patternfly/react-code-editor@6.2.1-prerelease.8) (2025-04-17) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.6...@patternfly/react-code-editor@6.2.1-prerelease.7) (2025-04-15) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.5...@patternfly/react-code-editor@6.2.1-prerelease.6) (2025-04-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.49...@patternfly/react-code-editor@4.3.50) (2021-09-10) +## [6.2.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.4...@patternfly/react-code-editor@6.2.1-prerelease.5) (2025-04-14) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.3...@patternfly/react-code-editor@6.2.1-prerelease.4) (2025-04-14) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.2...@patternfly/react-code-editor@6.2.1-prerelease.3) (2025-04-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.48...@patternfly/react-code-editor@4.3.49) (2021-09-10) +## [6.2.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.1...@patternfly/react-code-editor@6.2.1-prerelease.2) (2025-04-10) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.1-prerelease.0...@patternfly/react-code-editor@6.2.1-prerelease.1) (2025-04-08) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.2.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0...@patternfly/react-code-editor@6.2.1-prerelease.0) (2025-04-08) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.47...@patternfly/react-code-editor@4.3.48) (2021-09-09) +# 6.2.0 (2025-04-07) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.39...@patternfly/react-code-editor@6.2.0-prerelease.40) (2025-04-01) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.38...@patternfly/react-code-editor@6.2.0-prerelease.39) (2025-03-28) +### Bug Fixes -## [4.3.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.46...@patternfly/react-code-editor@4.3.47) (2021-09-01) +- **CodeeEditor:** rendered file input when editor has content ([#11725](https://github.com/patternfly/patternfly-react/issues/11725)) ([61922a9](https://github.com/patternfly/patternfly-react/commit/61922a9b228ec872632c5c3fb5045034092043ab)) +# [6.2.0-prerelease.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.37...@patternfly/react-code-editor@6.2.0-prerelease.38) (2025-03-27) ### Bug Fixes -* **code-editor:** replace hardcoded empty state text with props and update microcopy ([#6241](https://github.com/patternfly/patternfly-react/issues/6241)) ([9cdd64b](https://github.com/patternfly/patternfly-react/commit/9cdd64bf9d2e63b2a7fa4bf905ed90e8cc64cc08)) +- **CodeEditor:** added hidden input back when editor is visible ([#11723](https://github.com/patternfly/patternfly-react/issues/11723)) ([0b8936d](https://github.com/patternfly/patternfly-react/commit/0b8936dcff4beee2a7791304350a296c52a3edbe)) + +# [6.2.0-prerelease.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.36...@patternfly/react-code-editor@6.2.0-prerelease.37) (2025-03-26) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.35...@patternfly/react-code-editor@6.2.0-prerelease.36) (2025-03-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.34...@patternfly/react-code-editor@6.2.0-prerelease.35) (2025-03-11) -## [4.3.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.45...@patternfly/react-code-editor@4.3.46) (2021-08-31) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.33...@patternfly/react-code-editor@6.2.0-prerelease.34) (2025-03-11) ### Bug Fixes -* **code-editor:** remove uneeded peer dep ([#6239](https://github.com/patternfly/patternfly-react/issues/6239)) ([5d51551](https://github.com/patternfly/patternfly-react/commit/5d51551a091ffd0ca83c0bb0ceca652228ed8936)) +- **CodeEditor:** only include pf-v6-c-code-editor\_\_upload when hovering is active over an empty state ([#11568](https://github.com/patternfly/patternfly-react/issues/11568)) ([a53c929](https://github.com/patternfly/patternfly-react/commit/a53c9296b8378d5fa6ddf6def3896cb7d6239c80)) +# [6.2.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.32...@patternfly/react-code-editor@6.2.0-prerelease.33) (2025-03-11) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.31...@patternfly/react-code-editor@6.2.0-prerelease.32) (2025-03-10) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.44...@patternfly/react-code-editor@4.3.45) (2021-08-31) +# [6.2.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.30...@patternfly/react-code-editor@6.2.0-prerelease.31) (2025-03-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.29...@patternfly/react-code-editor@6.2.0-prerelease.30) (2025-03-06) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.28...@patternfly/react-code-editor@6.2.0-prerelease.29) (2025-03-05) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.43...@patternfly/react-code-editor@4.3.44) (2021-08-31) +# [6.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.27...@patternfly/react-code-editor@6.2.0-prerelease.28) (2025-03-04) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.26...@patternfly/react-code-editor@6.2.0-prerelease.27) (2025-03-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.25...@patternfly/react-code-editor@6.2.0-prerelease.26) (2025-02-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.42...@patternfly/react-code-editor@4.3.43) (2021-08-30) +# [6.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.24...@patternfly/react-code-editor@6.2.0-prerelease.25) (2025-02-25) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.23...@patternfly/react-code-editor@6.2.0-prerelease.24) (2025-02-24) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.22...@patternfly/react-code-editor@6.2.0-prerelease.23) (2025-02-24) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.41...@patternfly/react-code-editor@4.3.42) (2021-08-23) +# [6.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.21...@patternfly/react-code-editor@6.2.0-prerelease.22) (2025-02-20) -**Note:** Version bump only for package @patternfly/react-code-editor +### Bug Fixes +- **FileUpload:** hid input of type file from AT ([#11438](https://github.com/patternfly/patternfly-react/issues/11438)) ([9b41c4f](https://github.com/patternfly/patternfly-react/commit/9b41c4fcc72b3ade937dddf144bb387b9866cb95)) +# [6.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.20...@patternfly/react-code-editor@6.2.0-prerelease.21) (2025-02-17) +### Bug Fixes +- **CodeEditor:** do not include extra div if `headerMainContent` is unset ([#11534](https://github.com/patternfly/patternfly-react/issues/11534)) ([86ff923](https://github.com/patternfly/patternfly-react/commit/86ff9239f935b974896958ff4b3c4af5b8d98825)) +- **CodeEditor:** ensure that handleResize works when viewport shrinks ([#11532](https://github.com/patternfly/patternfly-react/issues/11532)) ([c06dbde](https://github.com/patternfly/patternfly-react/commit/c06dbdec017daa3b84e7af02a2e57b9a7efd0faa)) -## [4.3.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.40...@patternfly/react-code-editor@4.3.41) (2021-08-23) +# [6.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.19...@patternfly/react-code-editor@6.2.0-prerelease.20) (2025-02-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.18...@patternfly/react-code-editor@6.2.0-prerelease.19) (2025-02-13) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.17...@patternfly/react-code-editor@6.2.0-prerelease.18) (2025-02-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.39...@patternfly/react-code-editor@4.3.40) (2021-08-23) +# [6.2.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.16...@patternfly/react-code-editor@6.2.0-prerelease.17) (2025-02-12) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.15...@patternfly/react-code-editor@6.2.0-prerelease.16) (2025-01-28) +**Note:** Version bump only for package @patternfly/react-code-editor + +# [6.2.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.14...@patternfly/react-code-editor@6.2.0-prerelease.15) (2025-01-28) +### Bug Fixes +- **Button:** updated rendering of aria-disabled attribute ([#11478](https://github.com/patternfly/patternfly-react/issues/11478)) ([058b14f](https://github.com/patternfly/patternfly-react/commit/058b14fc93233860cd604cdfb60f7c666cc0d436)) -## [4.3.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.38...@patternfly/react-code-editor@4.3.39) (2021-08-23) +# [6.2.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.13...@patternfly/react-code-editor@6.2.0-prerelease.14) (2025-01-27) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.12...@patternfly/react-code-editor@6.2.0-prerelease.13) (2025-01-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.11...@patternfly/react-code-editor@6.2.0-prerelease.12) (2025-01-24) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.37...@patternfly/react-code-editor@4.3.38) (2021-08-20) +# [6.2.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.10...@patternfly/react-code-editor@6.2.0-prerelease.11) (2025-01-24) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.9...@patternfly/react-code-editor@6.2.0-prerelease.10) (2025-01-23) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.8...@patternfly/react-code-editor@6.2.0-prerelease.9) (2025-01-23) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.36...@patternfly/react-code-editor@4.3.37) (2021-08-20) +# [6.2.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.7...@patternfly/react-code-editor@6.2.0-prerelease.8) (2025-01-21) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.6...@patternfly/react-code-editor@6.2.0-prerelease.7) (2025-01-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.5...@patternfly/react-code-editor@6.2.0-prerelease.6) (2025-01-20) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.35...@patternfly/react-code-editor@4.3.36) (2021-08-20) +# [6.2.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.4...@patternfly/react-code-editor@6.2.0-prerelease.5) (2025-01-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.3...@patternfly/react-code-editor@6.2.0-prerelease.4) (2025-01-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.2...@patternfly/react-code-editor@6.2.0-prerelease.3) (2025-01-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.34...@patternfly/react-code-editor@4.3.35) (2021-08-19) +# [6.2.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.1...@patternfly/react-code-editor@6.2.0-prerelease.2) (2025-01-10) +**Note:** Version bump only for package @patternfly/react-code-editor -### Bug Fixes +# [6.2.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.2.0-prerelease.0...@patternfly/react-code-editor@6.2.0-prerelease.1) (2025-01-10) -* **examples:** updating example microcopy ([#6196](https://github.com/patternfly/patternfly-react/issues/6196)) ([b1d90f2](https://github.com/patternfly/patternfly-react/commit/b1d90f2c3e05eb6f5ee9aaa34b46a5a5d7a203fd)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.2.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.1-prerelease.2...@patternfly/react-code-editor@6.2.0-prerelease.0) (2025-01-06) +**Note:** Version bump only for package @patternfly/react-code-editor +## [6.1.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.1-prerelease.1...@patternfly/react-code-editor@6.1.1-prerelease.2) (2025-01-06) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.33...@patternfly/react-code-editor@4.3.34) (2021-08-19) +## [6.1.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.1-prerelease.0...@patternfly/react-code-editor@6.1.1-prerelease.1) (2024-12-19) **Note:** Version bump only for package @patternfly/react-code-editor +## [6.1.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0...@patternfly/react-code-editor@6.1.1-prerelease.0) (2024-12-18) +**Note:** Version bump only for package @patternfly/react-code-editor + +# 6.1.0 (2024-12-16) +### Bug Fixes +- Update promote.sh to release 6.1.0 ([2b5106f](https://github.com/patternfly/patternfly-react/commit/2b5106ff88ce207d4a9ed2066fd390009e81fb79)) -## [4.3.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.32...@patternfly/react-code-editor@4.3.33) (2021-08-19) +# [6.1.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.15...@patternfly/react-code-editor@6.1.0-prerelease.16) (2024-12-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.14...@patternfly/react-code-editor@6.1.0-prerelease.15) (2024-12-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.13...@patternfly/react-code-editor@6.1.0-prerelease.14) (2024-12-04) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.31...@patternfly/react-code-editor@4.3.32) (2021-08-18) +# [6.1.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.12...@patternfly/react-code-editor@6.1.0-prerelease.13) (2024-12-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.11...@patternfly/react-code-editor@6.1.0-prerelease.12) (2024-12-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.10...@patternfly/react-code-editor@6.1.0-prerelease.11) (2024-11-25) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.30...@patternfly/react-code-editor@4.3.31) (2021-08-18) +# [6.1.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.9...@patternfly/react-code-editor@6.1.0-prerelease.10) (2024-11-20) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.8...@patternfly/react-code-editor@6.1.0-prerelease.9) (2024-11-20) + +### Bug Fixes +- **deps:** update dependency react-dropzone to v14.3.5 (main) ([#11152](https://github.com/patternfly/patternfly-react/issues/11152)) ([849b347](https://github.com/patternfly/patternfly-react/commit/849b3477cf080fcc047f21824ab742b58dcd81e8)) +# [6.1.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.7...@patternfly/react-code-editor@6.1.0-prerelease.8) (2024-11-20) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.29...@patternfly/react-code-editor@4.3.30) (2021-08-17) +# [6.1.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.6...@patternfly/react-code-editor@6.1.0-prerelease.7) (2024-11-19) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.5...@patternfly/react-code-editor@6.1.0-prerelease.6) (2024-11-19) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.4...@patternfly/react-code-editor@6.1.0-prerelease.5) (2024-11-18) +### Bug Fixes +- **deps:** update dependency tslib to ^2.8.1 ([#11222](https://github.com/patternfly/patternfly-react/issues/11222)) ([7c90e9b](https://github.com/patternfly/patternfly-react/commit/7c90e9bff23083f097e78246570be60dacfb27c0)) -## [4.3.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.28...@patternfly/react-code-editor@4.3.29) (2021-08-16) +# [6.1.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.3...@patternfly/react-code-editor@6.1.0-prerelease.4) (2024-11-15) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.2...@patternfly/react-code-editor@6.1.0-prerelease.3) (2024-11-14) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.1.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.1...@patternfly/react-code-editor@6.1.0-prerelease.2) (2024-11-13) +### Bug Fixes +- **CodeEditor:** Set default height ([#11014](https://github.com/patternfly/patternfly-react/issues/11014)) ([6ddfc93](https://github.com/patternfly/patternfly-react/commit/6ddfc93376a48028fed46948b08a185e3c9617f6)) -## [4.3.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.27...@patternfly/react-code-editor@4.3.28) (2021-08-12) +# [6.1.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.1.0-prerelease.0...@patternfly/react-code-editor@6.1.0-prerelease.1) (2024-10-30) **Note:** Version bump only for package @patternfly/react-code-editor +# 6.1.0-prerelease.0 (2024-10-24) +**Note:** Version bump only for package @patternfly/react-code-editor +# 6.0.0 (2024-10-24) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.26...@patternfly/react-code-editor@4.3.27) (2021-08-11) +# [6.0.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.22...@patternfly/react-code-editor@6.0.0-prerelease.23) (2024-10-23) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.21...@patternfly/react-code-editor@6.0.0-prerelease.22) (2024-10-23) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.20...@patternfly/react-code-editor@6.0.0-prerelease.21) (2024-10-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.25...@patternfly/react-code-editor@4.3.26) (2021-08-11) +# [6.0.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.19...@patternfly/react-code-editor@6.0.0-prerelease.20) (2024-09-30) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.18...@patternfly/react-code-editor@6.0.0-prerelease.19) (2024-09-26) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.17...@patternfly/react-code-editor@6.0.0-prerelease.18) (2024-09-26) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.24...@patternfly/react-code-editor@4.3.25) (2021-08-10) +# [6.0.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.16...@patternfly/react-code-editor@6.0.0-prerelease.17) (2024-09-24) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.15...@patternfly/react-code-editor@6.0.0-prerelease.16) (2024-09-24) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.14...@patternfly/react-code-editor@6.0.0-prerelease.15) (2024-09-23) +### Bug Fixes +- **table:** update v5 to v6 for docs, description list, draggable, Th ([#10968](https://github.com/patternfly/patternfly-react/issues/10968)) ([db72b52](https://github.com/patternfly/patternfly-react/commit/db72b5287c18d023c094be247a46f9352d50fd7b)) -## [4.3.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.23...@patternfly/react-code-editor@4.3.24) (2021-08-10) +# [6.0.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.13...@patternfly/react-code-editor@6.0.0-prerelease.14) (2024-09-20) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.12...@patternfly/react-code-editor@6.0.0-prerelease.13) (2024-09-19) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.11...@patternfly/react-code-editor@6.0.0-prerelease.12) (2024-09-18) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.22...@patternfly/react-code-editor@4.3.23) (2021-08-09) +# [6.0.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.10...@patternfly/react-code-editor@6.0.0-prerelease.11) (2024-09-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.9...@patternfly/react-code-editor@6.0.0-prerelease.10) (2024-09-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.8...@patternfly/react-code-editor@6.0.0-prerelease.9) (2024-09-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.21...@patternfly/react-code-editor@4.3.22) (2021-08-03) +# [6.0.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.7...@patternfly/react-code-editor@6.0.0-prerelease.8) (2024-09-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.6...@patternfly/react-code-editor@6.0.0-prerelease.7) (2024-09-12) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.5...@patternfly/react-code-editor@6.0.0-prerelease.6) (2024-09-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.20...@patternfly/react-code-editor@4.3.21) (2021-08-02) +# [6.0.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.4...@patternfly/react-code-editor@6.0.0-prerelease.5) (2024-09-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.3...@patternfly/react-code-editor@6.0.0-prerelease.4) (2024-09-10) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.2...@patternfly/react-code-editor@6.0.0-prerelease.3) (2024-09-10) +### Bug Fixes +- **deps:** update dependency tslib to ^2.7.0 ([#10949](https://github.com/patternfly/patternfly-react/issues/10949)) ([024b3cc](https://github.com/patternfly/patternfly-react/commit/024b3cc4b1afd4ba9f2dc774c0842712d4fbab1a)) -## [4.3.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.19...@patternfly/react-code-editor@4.3.20) (2021-08-02) +# [6.0.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-prerelease.1...@patternfly/react-code-editor@6.0.0-prerelease.2) (2024-09-09) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.106...@patternfly/react-code-editor@6.0.0-prerelease.1) (2024-09-07) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.106](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.105...@patternfly/react-code-editor@6.0.0-alpha.106) (2024-08-30) +### Bug Fixes +- **Button:** rendered position modifier only when children are passed ([#10864](https://github.com/patternfly/patternfly-react/issues/10864)) ([3ed73d3](https://github.com/patternfly/patternfly-react/commit/3ed73d3dc78ba229b184bc4e91cc11f45ccc94c3)) -## [4.3.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.18...@patternfly/react-code-editor@4.3.19) (2021-08-02) +# [6.0.0-alpha.105](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.104...@patternfly/react-code-editor@6.0.0-alpha.105) (2024-08-28) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.104](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.103...@patternfly/react-code-editor@6.0.0-alpha.104) (2024-08-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.103](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.102...@patternfly/react-code-editor@6.0.0-alpha.103) (2024-08-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.17...@patternfly/react-code-editor@4.3.18) (2021-07-30) +# [6.0.0-alpha.102](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.101...@patternfly/react-code-editor@6.0.0-alpha.102) (2024-08-21) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.101](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.100...@patternfly/react-code-editor@6.0.0-alpha.101) (2024-08-19) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.100](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.99...@patternfly/react-code-editor@6.0.0-alpha.100) (2024-08-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.16...@patternfly/react-code-editor@4.3.17) (2021-07-29) +# [6.0.0-alpha.99](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.98...@patternfly/react-code-editor@6.0.0-alpha.99) (2024-08-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.98](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.97...@patternfly/react-code-editor@6.0.0-alpha.98) (2024-08-12) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.97](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.96...@patternfly/react-code-editor@6.0.0-alpha.97) (2024-08-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.15...@patternfly/react-code-editor@4.3.16) (2021-07-29) +# [6.0.0-alpha.96](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.95...@patternfly/react-code-editor@6.0.0-alpha.96) (2024-08-08) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.95](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.94...@patternfly/react-code-editor@6.0.0-alpha.95) (2024-08-01) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.94](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.93...@patternfly/react-code-editor@6.0.0-alpha.94) (2024-07-29) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.14...@patternfly/react-code-editor@4.3.15) (2021-07-28) +# [6.0.0-alpha.93](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.92...@patternfly/react-code-editor@6.0.0-alpha.93) (2024-07-29) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.92](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.91...@patternfly/react-code-editor@6.0.0-alpha.92) (2024-07-29) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.91](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.90...@patternfly/react-code-editor@6.0.0-alpha.91) (2024-07-29) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.13...@patternfly/react-code-editor@4.3.14) (2021-07-28) +# [6.0.0-alpha.90](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.89...@patternfly/react-code-editor@6.0.0-alpha.90) (2024-07-23) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.89](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.88...@patternfly/react-code-editor@6.0.0-alpha.89) (2024-07-22) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.88](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.87...@patternfly/react-code-editor@6.0.0-alpha.88) (2024-07-22) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.12...@patternfly/react-code-editor@4.3.13) (2021-07-27) +# [6.0.0-alpha.87](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.86...@patternfly/react-code-editor@6.0.0-alpha.87) (2024-07-22) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.86](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.85...@patternfly/react-code-editor@6.0.0-alpha.86) (2024-07-19) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.85](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.84...@patternfly/react-code-editor@6.0.0-alpha.85) (2024-07-18) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.11...@patternfly/react-code-editor@4.3.12) (2021-07-27) +# [6.0.0-alpha.84](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.83...@patternfly/react-code-editor@6.0.0-alpha.84) (2024-07-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.83](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.82...@patternfly/react-code-editor@6.0.0-alpha.83) (2024-07-15) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.82](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.81...@patternfly/react-code-editor@6.0.0-alpha.82) (2024-07-15) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.10...@patternfly/react-code-editor@4.3.11) (2021-07-23) +# [6.0.0-alpha.81](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.80...@patternfly/react-code-editor@6.0.0-alpha.81) (2024-07-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.80](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.79...@patternfly/react-code-editor@6.0.0-alpha.80) (2024-07-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.78...@patternfly/react-code-editor@6.0.0-alpha.79) (2024-07-08) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.9...@patternfly/react-code-editor@4.3.10) (2021-07-21) +# [6.0.0-alpha.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.77...@patternfly/react-code-editor@6.0.0-alpha.78) (2024-07-03) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.76...@patternfly/react-code-editor@6.0.0-alpha.77) (2024-07-03) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.75...@patternfly/react-code-editor@6.0.0-alpha.76) (2024-07-02) +### Features +- **Button:** add text wrapper, update icon usage ([#10663](https://github.com/patternfly/patternfly-react/issues/10663)) ([eca5878](https://github.com/patternfly/patternfly-react/commit/eca58789d1f07753657372a46a20c147f984b998)) -## [4.3.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.8...@patternfly/react-code-editor@4.3.9) (2021-07-21) +# [6.0.0-alpha.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.74...@patternfly/react-code-editor@6.0.0-alpha.75) (2024-07-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.73...@patternfly/react-code-editor@6.0.0-alpha.74) (2024-07-01) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.72...@patternfly/react-code-editor@6.0.0-alpha.73) (2024-06-26) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.7...@patternfly/react-code-editor@4.3.8) (2021-07-21) +# [6.0.0-alpha.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.71...@patternfly/react-code-editor@6.0.0-alpha.72) (2024-06-25) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.70...@patternfly/react-code-editor@6.0.0-alpha.71) (2024-06-25) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.69...@patternfly/react-code-editor@6.0.0-alpha.70) (2024-06-20) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.6...@patternfly/react-code-editor@4.3.7) (2021-07-20) +# [6.0.0-alpha.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.68...@patternfly/react-code-editor@6.0.0-alpha.69) (2024-06-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.67...@patternfly/react-code-editor@6.0.0-alpha.68) (2024-06-12) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.66...@patternfly/react-code-editor@6.0.0-alpha.67) (2024-06-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.5...@patternfly/react-code-editor@4.3.6) (2021-07-20) +# [6.0.0-alpha.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.65...@patternfly/react-code-editor@6.0.0-alpha.66) (2024-06-06) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.64...@patternfly/react-code-editor@6.0.0-alpha.65) (2024-06-06) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.63...@patternfly/react-code-editor@6.0.0-alpha.64) (2024-06-05) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.4...@patternfly/react-code-editor@4.3.5) (2021-07-19) +# [6.0.0-alpha.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.62...@patternfly/react-code-editor@6.0.0-alpha.63) (2024-06-05) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.61...@patternfly/react-code-editor@6.0.0-alpha.62) (2024-06-04) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.60...@patternfly/react-code-editor@6.0.0-alpha.61) (2024-05-31) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.3...@patternfly/react-code-editor@4.3.4) (2021-07-16) +# 6.0.0-alpha.60 (2024-05-23) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.58...@patternfly/react-code-editor@6.0.0-alpha.59) (2024-05-21) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.57...@patternfly/react-code-editor@6.0.0-alpha.58) (2024-05-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.2...@patternfly/react-code-editor@4.3.3) (2021-07-15) +# [6.0.0-alpha.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.56...@patternfly/react-code-editor@6.0.0-alpha.57) (2024-05-15) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.55...@patternfly/react-code-editor@6.0.0-alpha.56) (2024-05-08) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.54...@patternfly/react-code-editor@6.0.0-alpha.55) (2024-05-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.53...@patternfly/react-code-editor@6.0.0-alpha.54) (2024-04-29) -## [4.3.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.1...@patternfly/react-code-editor@4.3.2) (2021-07-15) +**Note:** Version bump only for package @patternfly/react-code-editor +# 6.0.0-alpha.53 (2024-04-26) ### Bug Fixes -* **code-editor:** add more languages support ([#6006](https://github.com/patternfly/patternfly-react/issues/6006)) ([a9b78e2](https://github.com/patternfly/patternfly-react/commit/a9b78e28813703bf14f65f27e1018d2e0a7abf76)) +- **helpers:** Updated OUIA ID prefix to PF6 ([#10292](https://github.com/patternfly/patternfly-react/issues/10292)) ([1c7af7a](https://github.com/patternfly/patternfly-react/commit/1c7af7ab9f352b9ad02caabb1deef08cf69e0950)) +# [6.0.0-alpha.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.51...@patternfly/react-code-editor@6.0.0-alpha.52) (2024-04-24) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.50...@patternfly/react-code-editor@6.0.0-alpha.51) (2024-04-22) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.3.0...@patternfly/react-code-editor@4.3.1) (2021-07-14) +# [5.3.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.26...@patternfly/react-code-editor@5.3.0-prerelease.27) (2024-04-09) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.25...@patternfly/react-code-editor@5.3.0-prerelease.26) (2024-04-08) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.24...@patternfly/react-code-editor@5.3.0-prerelease.25) (2024-04-01) +**Note:** Version bump only for package @patternfly/react-code-editor -# [4.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.105...@patternfly/react-code-editor@4.3.0) (2021-07-13) +# 5.3.0-prerelease.24 (2024-03-29) +**Note:** Version bump only for package @patternfly/react-code-editor -### Bug Fixes +# [5.3.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.22...@patternfly/react-code-editor@5.3.0-prerelease.23) (2024-03-28) -* **codeeditor:** show toolbar if there are custom controls ([#6025](https://github.com/patternfly/patternfly-react/issues/6025)) ([dad127a](https://github.com/patternfly/patternfly-react/commit/dad127a037bc8c921a6921a01ed702eb72cfdbd9)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.21...@patternfly/react-code-editor@5.3.0-prerelease.22) (2024-03-28) -### Features +**Note:** Version bump only for package @patternfly/react-code-editor + +# [5.3.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.20...@patternfly/react-code-editor@5.3.0-prerelease.21) (2024-03-27) -* **code-editor:** add showEditor prop ([#6022](https://github.com/patternfly/patternfly-react/issues/6022)) ([daf182a](https://github.com/patternfly/patternfly-react/commit/daf182af298e57018f06ce887001a0b1acc43167)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.19...@patternfly/react-code-editor@5.3.0-prerelease.20) (2024-03-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.18...@patternfly/react-code-editor@5.3.0-prerelease.19) (2024-03-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.105](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.104...@patternfly/react-code-editor@4.2.105) (2021-07-13) +# [5.3.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.17...@patternfly/react-code-editor@5.3.0-prerelease.18) (2024-03-26) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.3.0-prerelease.17 (2024-03-26) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.15...@patternfly/react-code-editor@5.3.0-prerelease.16) (2024-03-26) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.104](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.103...@patternfly/react-code-editor@4.2.104) (2021-07-12) +# [5.3.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.14...@patternfly/react-code-editor@5.3.0-prerelease.15) (2024-03-26) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.13...@patternfly/react-code-editor@5.3.0-prerelease.14) (2024-03-25) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.12...@patternfly/react-code-editor@5.3.0-prerelease.13) (2024-03-22) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.103](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.102...@patternfly/react-code-editor@4.2.103) (2021-07-09) +# 5.3.0-prerelease.12 (2024-03-20) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.10...@patternfly/react-code-editor@5.3.0-prerelease.11) (2024-03-15) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.9...@patternfly/react-code-editor@5.3.0-prerelease.10) (2024-03-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.102](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.101...@patternfly/react-code-editor@4.2.102) (2021-07-09) +# 5.3.0-prerelease.9 (2024-03-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.7...@patternfly/react-code-editor@5.3.0-prerelease.8) (2024-02-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.6...@patternfly/react-code-editor@5.3.0-prerelease.7) (2024-02-28) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.101](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.100...@patternfly/react-code-editor@4.2.101) (2021-07-09) +# [5.3.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.5...@patternfly/react-code-editor@5.3.0-prerelease.6) (2024-02-28) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.4...@patternfly/react-code-editor@5.3.0-prerelease.5) (2024-02-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.3...@patternfly/react-code-editor@5.3.0-prerelease.4) (2024-02-26) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.100](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.99...@patternfly/react-code-editor@4.2.100) (2021-07-09) +# [5.3.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.2...@patternfly/react-code-editor@5.3.0-prerelease.3) (2024-02-19) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.1...@patternfly/react-code-editor@5.3.0-prerelease.2) (2024-02-19) +**Note:** Version bump only for package @patternfly/react-code-editor +# 5.3.0-prerelease.1 (2024-02-15) +### Features -## [4.2.99](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.98...@patternfly/react-code-editor@4.2.99) (2021-07-08) +- **CodeEditor:** pass additional props to monaco-editor, update readme ([#10080](https://github.com/patternfly/patternfly-react/issues/10080)) ([8c43ef7](https://github.com/patternfly/patternfly-react/commit/8c43ef7bfc044396a0bf31985b2ba3e4b4de91ef)) -**Note:** Version bump only for package @patternfly/react-code-editor +# 5.3.0-prerelease.0 (2024-02-02) +# 5.2.0 (2024-02-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# 5.2.0 (2024-02-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.98](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.97...@patternfly/react-code-editor@4.2.98) (2021-07-07) +# 5.2.0-prerelease.51 (2024-02-02) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.2.0-prerelease.50 (2024-01-29) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.48...@patternfly/react-code-editor@5.2.0-prerelease.49) (2024-01-17) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.97](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.96...@patternfly/react-code-editor@4.2.97) (2021-07-01) +# 5.2.0-prerelease.48 (2024-01-16) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.46...@patternfly/react-code-editor@5.2.0-prerelease.47) (2024-01-15) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.45...@patternfly/react-code-editor@5.2.0-prerelease.46) (2024-01-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.96](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.95...@patternfly/react-code-editor@4.2.96) (2021-07-01) +# [5.2.0-prerelease.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.44...@patternfly/react-code-editor@5.2.0-prerelease.45) (2024-01-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.43...@patternfly/react-code-editor@5.2.0-prerelease.44) (2024-01-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.42...@patternfly/react-code-editor@5.2.0-prerelease.43) (2024-01-08) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.95](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.94...@patternfly/react-code-editor@4.2.95) (2021-06-30) +# [5.2.0-prerelease.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.41...@patternfly/react-code-editor@5.2.0-prerelease.42) (2024-01-05) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.40...@patternfly/react-code-editor@5.2.0-prerelease.41) (2024-01-05) +### Features +- **CodeEditor:** use new monaco package ([#9842](https://github.com/patternfly/patternfly-react/issues/9842)) ([54dd134](https://github.com/patternfly/patternfly-react/commit/54dd134d6c67c4fc1d7630fd1e7c718f66061342)) +# [5.2.0-prerelease.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.39...@patternfly/react-code-editor@5.2.0-prerelease.40) (2024-01-04) -## [4.2.94](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.93...@patternfly/react-code-editor@4.2.94) (2021-06-30) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.38...@patternfly/react-code-editor@5.2.0-prerelease.39) (2024-01-03) -### Bug Fixes +**Note:** Version bump only for package @patternfly/react-code-editor -* **ci:** change master branch to main ([4ac4129](https://github.com/patternfly/patternfly-react/commit/4ac4129e8da9a37367ea7612019f8d7af1ed8836)) +# [5.2.0-prerelease.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.37...@patternfly/react-code-editor@5.2.0-prerelease.38) (2024-01-02) +**Note:** Version bump only for package @patternfly/react-code-editor + +# [5.2.0-prerelease.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.36...@patternfly/react-code-editor@5.2.0-prerelease.37) (2023-12-20) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.35...@patternfly/react-code-editor@5.2.0-prerelease.36) (2023-12-14) +**Note:** Version bump only for package @patternfly/react-code-editor + +# [5.2.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.34...@patternfly/react-code-editor@5.2.0-prerelease.35) (2023-12-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.93](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.92...@patternfly/react-code-editor@4.2.93) (2021-06-28) +# [5.2.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.33...@patternfly/react-code-editor@5.2.0-prerelease.34) (2023-12-07) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.32...@patternfly/react-code-editor@5.2.0-prerelease.33) (2023-12-06) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.31...@patternfly/react-code-editor@5.2.0-prerelease.32) (2023-11-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.92](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.91...@patternfly/react-code-editor@4.2.92) (2021-06-21) +# [5.2.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.30...@patternfly/react-code-editor@5.2.0-prerelease.31) (2023-11-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.29...@patternfly/react-code-editor@5.2.0-prerelease.30) (2023-11-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.28...@patternfly/react-code-editor@5.2.0-prerelease.29) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.91](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.90...@patternfly/react-code-editor@4.2.91) (2021-06-18) +# [5.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.27...@patternfly/react-code-editor@5.2.0-prerelease.28) (2023-11-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.26...@patternfly/react-code-editor@5.2.0-prerelease.27) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.25...@patternfly/react-code-editor@5.2.0-prerelease.26) (2023-11-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.90](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.89...@patternfly/react-code-editor@4.2.90) (2021-06-18) +# [5.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.24...@patternfly/react-code-editor@5.2.0-prerelease.25) (2023-11-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.23...@patternfly/react-code-editor@5.2.0-prerelease.24) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.22...@patternfly/react-code-editor@5.2.0-prerelease.23) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.89](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.88...@patternfly/react-code-editor@4.2.89) (2021-06-18) +# [5.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.21...@patternfly/react-code-editor@5.2.0-prerelease.22) (2023-11-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.20...@patternfly/react-code-editor@5.2.0-prerelease.21) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.19...@patternfly/react-code-editor@5.2.0-prerelease.20) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.88](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.87...@patternfly/react-code-editor@4.2.88) (2021-06-18) +# [6.0.0-alpha.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.49...@patternfly/react-code-editor@6.0.0-alpha.50) (2024-04-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.48...@patternfly/react-code-editor@6.0.0-alpha.49) (2024-03-29) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.47...@patternfly/react-code-editor@6.0.0-alpha.48) (2024-03-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.87](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.86...@patternfly/react-code-editor@4.2.87) (2021-06-17) +# [6.0.0-alpha.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.46...@patternfly/react-code-editor@6.0.0-alpha.47) (2024-03-27) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.45...@patternfly/react-code-editor@6.0.0-alpha.46) (2024-03-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.44...@patternfly/react-code-editor@6.0.0-alpha.45) (2024-03-26) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.86](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.85...@patternfly/react-code-editor@4.2.86) (2021-06-17) +# [6.0.0-alpha.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.43...@patternfly/react-code-editor@6.0.0-alpha.44) (2024-03-22) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.42...@patternfly/react-code-editor@6.0.0-alpha.43) (2024-03-18) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.41...@patternfly/react-code-editor@6.0.0-alpha.42) (2024-03-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.85](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.84...@patternfly/react-code-editor@4.2.85) (2021-06-17) +# [6.0.0-alpha.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.40...@patternfly/react-code-editor@6.0.0-alpha.41) (2024-03-12) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.39...@patternfly/react-code-editor@6.0.0-alpha.40) (2024-03-08) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.38...@patternfly/react-code-editor@6.0.0-alpha.39) (2024-03-01) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.84](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.83...@patternfly/react-code-editor@4.2.84) (2021-06-17) +# [6.0.0-alpha.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.37...@patternfly/react-code-editor@6.0.0-alpha.38) (2024-02-28) **Note:** Version bump only for package @patternfly/react-code-editor +# 6.0.0-alpha.37 (2024-02-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.35...@patternfly/react-code-editor@6.0.0-alpha.36) (2024-02-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.83](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.82...@patternfly/react-code-editor@4.2.83) (2021-06-17) +# [6.0.0-alpha.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.34...@patternfly/react-code-editor@6.0.0-alpha.35) (2024-02-21) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.33...@patternfly/react-code-editor@6.0.0-alpha.34) (2024-02-19) +### Features +- **Chip:** use Label internally, deprecate Chip ([#10049](https://github.com/patternfly/patternfly-react/issues/10049)) ([5cdb725](https://github.com/patternfly/patternfly-react/commit/5cdb72536f8dd291e42be09bc6454ac591adc606)) +# [6.0.0-alpha.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.32...@patternfly/react-code-editor@6.0.0-alpha.33) (2024-02-16) -## [4.2.82](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.81...@patternfly/react-code-editor@4.2.82) (2021-06-16) +### Features -**Note:** Version bump only for package @patternfly/react-code-editor +- **CodeEditor,Divider:** consume penta & update core version ([#10081](https://github.com/patternfly/patternfly-react/issues/10081)) ([addda04](https://github.com/patternfly/patternfly-react/commit/addda044d7f6d91f3511c7a769b2707140df86d4)) +# [6.0.0-alpha.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.31...@patternfly/react-code-editor@6.0.0-alpha.32) (2024-02-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.30...@patternfly/react-code-editor@6.0.0-alpha.31) (2024-02-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.81](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.80...@patternfly/react-code-editor@4.2.81) (2021-06-16) +# [6.0.0-alpha.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.29...@patternfly/react-code-editor@6.0.0-alpha.30) (2024-02-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.28...@patternfly/react-code-editor@6.0.0-alpha.29) (2024-02-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.27...@patternfly/react-code-editor@6.0.0-alpha.28) (2024-02-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.80](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.79...@patternfly/react-code-editor@4.2.80) (2021-06-15) +# [6.0.0-alpha.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.26...@patternfly/react-code-editor@6.0.0-alpha.27) (2024-02-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.25...@patternfly/react-code-editor@6.0.0-alpha.26) (2024-02-01) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.24...@patternfly/react-code-editor@6.0.0-alpha.25) (2024-02-01) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.78...@patternfly/react-code-editor@4.2.79) (2021-06-15) +# [6.0.0-alpha.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.23...@patternfly/react-code-editor@6.0.0-alpha.24) (2024-01-31) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.22...@patternfly/react-code-editor@6.0.0-alpha.23) (2024-01-31) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.21...@patternfly/react-code-editor@6.0.0-alpha.22) (2024-01-31) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.77...@patternfly/react-code-editor@4.2.78) (2021-06-11) +# [6.0.0-alpha.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.20...@patternfly/react-code-editor@6.0.0-alpha.21) (2024-01-31) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.19...@patternfly/react-code-editor@6.0.0-alpha.20) (2024-01-26) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.18...@patternfly/react-code-editor@6.0.0-alpha.19) (2024-01-22) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.76...@patternfly/react-code-editor@4.2.77) (2021-06-10) +# [6.0.0-alpha.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.17...@patternfly/react-code-editor@6.0.0-alpha.18) (2024-01-22) **Note:** Version bump only for package @patternfly/react-code-editor +# 6.0.0-alpha.17 (2024-01-19) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.15...@patternfly/react-code-editor@6.0.0-alpha.16) (2024-01-18) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.75...@patternfly/react-code-editor@4.2.76) (2021-06-04) +# [6.0.0-alpha.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.14...@patternfly/react-code-editor@6.0.0-alpha.15) (2024-01-18) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.13...@patternfly/react-code-editor@6.0.0-alpha.14) (2024-01-17) +### Features +- **EmptyState:** update EmptyState with updates for penta ([#9947](https://github.com/patternfly/patternfly-react/issues/9947)) ([07cbb82](https://github.com/patternfly/patternfly-react/commit/07cbb8270627f9ade299b90eaf5dd4fd5fa6fe95)) - -## [4.2.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.74...@patternfly/react-code-editor@4.2.75) (2021-06-02) +# [6.0.0-alpha.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.12...@patternfly/react-code-editor@6.0.0-alpha.13) (2024-01-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.11...@patternfly/react-code-editor@6.0.0-alpha.12) (2024-01-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.10...@patternfly/react-code-editor@6.0.0-alpha.11) (2024-01-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.73...@patternfly/react-code-editor@4.2.74) (2021-06-02) +# [6.0.0-alpha.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.9...@patternfly/react-code-editor@6.0.0-alpha.10) (2024-01-12) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.8...@patternfly/react-code-editor@6.0.0-alpha.9) (2024-01-04) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.7...@patternfly/react-code-editor@6.0.0-alpha.8) (2024-01-04) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.72...@patternfly/react-code-editor@4.2.73) (2021-06-02) +# [6.0.0-alpha.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.6...@patternfly/react-code-editor@6.0.0-alpha.7) (2023-12-20) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.5...@patternfly/react-code-editor@6.0.0-alpha.6) (2023-12-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.4...@patternfly/react-code-editor@6.0.0-alpha.5) (2023-12-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.71...@patternfly/react-code-editor@4.2.72) (2021-06-01) +# [6.0.0-alpha.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.3...@patternfly/react-code-editor@6.0.0-alpha.4) (2023-12-06) **Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@6.0.0-alpha.2...@patternfly/react-code-editor@6.0.0-alpha.3) (2023-12-04) +**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.19...@patternfly/react-code-editor@6.0.0-alpha.2) (2023-11-16) +### Reverts -## [4.2.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.70...@patternfly/react-code-editor@4.2.71) (2021-06-01) +- Revert "Merge remote-tracking branch 'upstream/main' into v6" (#9791) ([b7e8065](https://github.com/patternfly/patternfly-react/commit/b7e80650d3e4cad7a657f6e5a3177485ca4f8c26)), closes [#9791](https://github.com/patternfly/patternfly-react/issues/9791) -**Note:** Version bump only for package @patternfly/react-code-editor +# [6.0.0-alpha.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.13...@patternfly/react-code-editor@6.0.0-alpha.1) (2023-09-29) +### Bug Fixes +- Release alphas from v6 and rebase from main ([#9692](https://github.com/patternfly/patternfly-react/issues/9692)) ([bb022ff](https://github.com/patternfly/patternfly-react/commit/bb022ffc65da8e8c5b5c984412f936cea9424676)), closes [#9651](https://github.com/patternfly/patternfly-react/issues/9651) [#9627](https://github.com/patternfly/patternfly-react/issues/9627) [#9555](https://github.com/patternfly/patternfly-react/issues/9555) [#9543](https://github.com/patternfly/patternfly-react/issues/9543) [#9578](https://github.com/patternfly/patternfly-react/issues/9578) [#9519](https://github.com/patternfly/patternfly-react/issues/9519) [#9603](https://github.com/patternfly/patternfly-react/issues/9603) [#9655](https://github.com/patternfly/patternfly-react/issues/9655) [#9614](https://github.com/patternfly/patternfly-react/issues/9614) [#9606](https://github.com/patternfly/patternfly-react/issues/9606) [#9628](https://github.com/patternfly/patternfly-react/issues/9628) [#9635](https://github.com/patternfly/patternfly-react/issues/9635) [#9649](https://github.com/patternfly/patternfly-react/issues/9649) [#9642](https://github.com/patternfly/patternfly-react/issues/9642) [#9633](https://github.com/patternfly/patternfly-react/issues/9633) [#9637](https://github.com/patternfly/patternfly-react/issues/9637) [#9584](https://github.com/patternfly/patternfly-react/issues/9584) [#9284](https://github.com/patternfly/patternfly-react/issues/9284) +## [5.1.1-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.21...@patternfly/react-code-editor@5.1.1-prerelease.22) (2023-09-25) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.69...@patternfly/react-code-editor@4.2.70) (2021-05-27) +## [5.1.1-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.20...@patternfly/react-code-editor@5.1.1-prerelease.21) (2023-09-25) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.19...@patternfly/react-code-editor@5.1.1-prerelease.20) (2023-09-22) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.18...@patternfly/react-code-editor@5.1.1-prerelease.19) (2023-09-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.68...@patternfly/react-code-editor@4.2.69) (2021-05-27) +## [5.1.1-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.17...@patternfly/react-code-editor@5.1.1-prerelease.18) (2023-09-21) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.16...@patternfly/react-code-editor@5.1.1-prerelease.17) (2023-09-21) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.15...@patternfly/react-code-editor@5.1.1-prerelease.16) (2023-09-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.67...@patternfly/react-code-editor@4.2.68) (2021-05-27) +## [5.1.1-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.14...@patternfly/react-code-editor@5.1.1-prerelease.15) (2023-09-21) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.13...@patternfly/react-code-editor@5.1.1-prerelease.14) (2023-09-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.30...@patternfly/react-code-editor@5.2.0-prerelease.31) (2023-11-17) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.66...@patternfly/react-code-editor@4.2.67) (2021-05-27) +# [5.2.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.29...@patternfly/react-code-editor@5.2.0-prerelease.30) (2023-11-16) +**Note:** Version bump only for package @patternfly/react-code-editor -### Bug Fixes +# [5.2.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.28...@patternfly/react-code-editor@5.2.0-prerelease.29) (2023-11-14) -* **tooltip:** change default entry and exit delay ([#5746](https://github.com/patternfly/patternfly-react/issues/5746)) ([9f35132](https://github.com/patternfly/patternfly-react/commit/9f351324257ad29a79dc92a1659801e20766e0f8)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.27...@patternfly/react-code-editor@5.2.0-prerelease.28) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.26...@patternfly/react-code-editor@5.2.0-prerelease.27) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.65...@patternfly/react-code-editor@4.2.66) (2021-05-26) +# [5.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.25...@patternfly/react-code-editor@5.2.0-prerelease.26) (2023-11-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.24...@patternfly/react-code-editor@5.2.0-prerelease.25) (2023-11-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.23...@patternfly/react-code-editor@5.2.0-prerelease.24) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.64...@patternfly/react-code-editor@4.2.65) (2021-05-26) +# [5.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.22...@patternfly/react-code-editor@5.2.0-prerelease.23) (2023-11-03) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.21...@patternfly/react-code-editor@5.2.0-prerelease.22) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.20...@patternfly/react-code-editor@5.2.0-prerelease.21) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.63...@patternfly/react-code-editor@4.2.64) (2021-05-25) +# [5.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.19...@patternfly/react-code-editor@5.2.0-prerelease.20) (2023-11-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.35...@patternfly/react-code-editor@5.2.0-prerelease.36) (2023-12-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.34...@patternfly/react-code-editor@5.2.0-prerelease.35) (2023-12-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.62...@patternfly/react-code-editor@4.2.63) (2021-05-25) +# [5.2.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.33...@patternfly/react-code-editor@5.2.0-prerelease.34) (2023-12-07) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.32...@patternfly/react-code-editor@5.2.0-prerelease.33) (2023-12-06) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.31...@patternfly/react-code-editor@5.2.0-prerelease.32) (2023-11-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.61...@patternfly/react-code-editor@4.2.62) (2021-05-24) +# [5.2.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.30...@patternfly/react-code-editor@5.2.0-prerelease.31) (2023-11-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.29...@patternfly/react-code-editor@5.2.0-prerelease.30) (2023-11-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.28...@patternfly/react-code-editor@5.2.0-prerelease.29) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.60...@patternfly/react-code-editor@4.2.61) (2021-05-21) +# [5.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.27...@patternfly/react-code-editor@5.2.0-prerelease.28) (2023-11-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.26...@patternfly/react-code-editor@5.2.0-prerelease.27) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.25...@patternfly/react-code-editor@5.2.0-prerelease.26) (2023-11-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.59...@patternfly/react-code-editor@4.2.60) (2021-05-19) +# [5.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.24...@patternfly/react-code-editor@5.2.0-prerelease.25) (2023-11-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.23...@patternfly/react-code-editor@5.2.0-prerelease.24) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.22...@patternfly/react-code-editor@5.2.0-prerelease.23) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.58...@patternfly/react-code-editor@4.2.59) (2021-05-17) +# [5.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.21...@patternfly/react-code-editor@5.2.0-prerelease.22) (2023-11-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.20...@patternfly/react-code-editor@5.2.0-prerelease.21) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.19...@patternfly/react-code-editor@5.2.0-prerelease.20) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.57...@patternfly/react-code-editor@4.2.58) (2021-05-13) +# [5.2.0-prerelease.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.48...@patternfly/react-code-editor@5.2.0-prerelease.49) (2024-01-17) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.2.0-prerelease.48 (2024-01-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.46...@patternfly/react-code-editor@5.2.0-prerelease.47) (2024-01-15) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.56...@patternfly/react-code-editor@4.2.57) (2021-05-12) +# [5.2.0-prerelease.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.45...@patternfly/react-code-editor@5.2.0-prerelease.46) (2024-01-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.44...@patternfly/react-code-editor@5.2.0-prerelease.45) (2024-01-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.43...@patternfly/react-code-editor@5.2.0-prerelease.44) (2024-01-09) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.55...@patternfly/react-code-editor@4.2.56) (2021-05-11) +# [5.2.0-prerelease.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.42...@patternfly/react-code-editor@5.2.0-prerelease.43) (2024-01-08) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.41...@patternfly/react-code-editor@5.2.0-prerelease.42) (2024-01-05) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.40...@patternfly/react-code-editor@5.2.0-prerelease.41) (2024-01-05) +### Features +- **CodeEditor:** use new monaco package ([#9842](https://github.com/patternfly/patternfly-react/issues/9842)) ([54dd134](https://github.com/patternfly/patternfly-react/commit/54dd134d6c67c4fc1d7630fd1e7c718f66061342)) -## [4.2.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.54...@patternfly/react-code-editor@4.2.55) (2021-05-10) +# [5.2.0-prerelease.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.39...@patternfly/react-code-editor@5.2.0-prerelease.40) (2024-01-04) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.38...@patternfly/react-code-editor@5.2.0-prerelease.39) (2024-01-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.37...@patternfly/react-code-editor@5.2.0-prerelease.38) (2024-01-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.53...@patternfly/react-code-editor@4.2.54) (2021-05-10) +# [5.2.0-prerelease.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.36...@patternfly/react-code-editor@5.2.0-prerelease.37) (2023-12-20) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.35...@patternfly/react-code-editor@5.2.0-prerelease.36) (2023-12-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.34...@patternfly/react-code-editor@5.2.0-prerelease.35) (2023-12-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.52...@patternfly/react-code-editor@4.2.53) (2021-05-07) +# [5.2.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.33...@patternfly/react-code-editor@5.2.0-prerelease.34) (2023-12-07) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.32...@patternfly/react-code-editor@5.2.0-prerelease.33) (2023-12-06) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.31...@patternfly/react-code-editor@5.2.0-prerelease.32) (2023-11-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.51...@patternfly/react-code-editor@4.2.52) (2021-05-07) +# [5.2.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.30...@patternfly/react-code-editor@5.2.0-prerelease.31) (2023-11-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.29...@patternfly/react-code-editor@5.2.0-prerelease.30) (2023-11-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.28...@patternfly/react-code-editor@5.2.0-prerelease.29) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.50...@patternfly/react-code-editor@4.2.51) (2021-05-07) +# [5.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.27...@patternfly/react-code-editor@5.2.0-prerelease.28) (2023-11-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.26...@patternfly/react-code-editor@5.2.0-prerelease.27) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.25...@patternfly/react-code-editor@5.2.0-prerelease.26) (2023-11-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.49...@patternfly/react-code-editor@4.2.50) (2021-05-06) +# [5.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.24...@patternfly/react-code-editor@5.2.0-prerelease.25) (2023-11-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.23...@patternfly/react-code-editor@5.2.0-prerelease.24) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.22...@patternfly/react-code-editor@5.2.0-prerelease.23) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.48...@patternfly/react-code-editor@4.2.49) (2021-05-06) +# [5.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.21...@patternfly/react-code-editor@5.2.0-prerelease.22) (2023-11-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.20...@patternfly/react-code-editor@5.2.0-prerelease.21) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.19...@patternfly/react-code-editor@5.2.0-prerelease.20) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.47...@patternfly/react-code-editor@4.2.48) (2021-05-06) +# [5.3.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.7...@patternfly/react-code-editor@5.3.0-prerelease.8) (2024-02-28) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.6...@patternfly/react-code-editor@5.3.0-prerelease.7) (2024-02-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.5...@patternfly/react-code-editor@5.3.0-prerelease.6) (2024-02-28) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.46...@patternfly/react-code-editor@4.2.47) (2021-05-05) +# [5.3.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.4...@patternfly/react-code-editor@5.3.0-prerelease.5) (2024-02-27) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.3...@patternfly/react-code-editor@5.3.0-prerelease.4) (2024-02-26) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.3.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.2...@patternfly/react-code-editor@5.3.0-prerelease.3) (2024-02-19) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.45...@patternfly/react-code-editor@4.2.46) (2021-05-04) +# [5.3.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.3.0-prerelease.1...@patternfly/react-code-editor@5.3.0-prerelease.2) (2024-02-19) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.3.0-prerelease.1 (2024-02-15) +### Features +- **CodeEditor:** pass additional props to monaco-editor, update readme ([#10080](https://github.com/patternfly/patternfly-react/issues/10080)) ([8c43ef7](https://github.com/patternfly/patternfly-react/commit/8c43ef7bfc044396a0bf31985b2ba3e4b4de91ef)) +# 5.3.0-prerelease.0 (2024-02-02) -## [4.2.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.44...@patternfly/react-code-editor@4.2.45) (2021-05-03) +# 5.2.0 (2024-02-02) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.2.0 (2024-02-02) +**Note:** Version bump only for package @patternfly/react-code-editor - - -## [4.2.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.43...@patternfly/react-code-editor@4.2.44) (2021-05-03) +# 5.2.0-prerelease.51 (2024-02-02) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.2.0-prerelease.50 (2024-01-29) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.48...@patternfly/react-code-editor@5.2.0-prerelease.49) (2024-01-17) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.42...@patternfly/react-code-editor@4.2.43) (2021-04-29) +# 5.2.0-prerelease.48 (2024-01-16) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.46...@patternfly/react-code-editor@5.2.0-prerelease.47) (2024-01-15) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.45...@patternfly/react-code-editor@5.2.0-prerelease.46) (2024-01-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.41...@patternfly/react-code-editor@4.2.42) (2021-04-26) +# [5.2.0-prerelease.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.44...@patternfly/react-code-editor@5.2.0-prerelease.45) (2024-01-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.43...@patternfly/react-code-editor@5.2.0-prerelease.44) (2024-01-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.42...@patternfly/react-code-editor@5.2.0-prerelease.43) (2024-01-08) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.40...@patternfly/react-code-editor@4.2.41) (2021-04-22) +# [5.2.0-prerelease.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.41...@patternfly/react-code-editor@5.2.0-prerelease.42) (2024-01-05) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.40...@patternfly/react-code-editor@5.2.0-prerelease.41) (2024-01-05) +### Features +- **CodeEditor:** use new monaco package ([#9842](https://github.com/patternfly/patternfly-react/issues/9842)) ([54dd134](https://github.com/patternfly/patternfly-react/commit/54dd134d6c67c4fc1d7630fd1e7c718f66061342)) - -## [4.2.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.39...@patternfly/react-code-editor@4.2.40) (2021-04-21) +# [5.2.0-prerelease.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.39...@patternfly/react-code-editor@5.2.0-prerelease.40) (2024-01-04) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.38...@patternfly/react-code-editor@5.2.0-prerelease.39) (2024-01-03) +**Note:** Version bump only for package @patternfly/react-code-editor - - -## [4.2.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.38...@patternfly/react-code-editor@4.2.39) (2021-04-20) +# [5.2.0-prerelease.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.37...@patternfly/react-code-editor@5.2.0-prerelease.38) (2024-01-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.36...@patternfly/react-code-editor@5.2.0-prerelease.37) (2023-12-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.35...@patternfly/react-code-editor@5.2.0-prerelease.36) (2023-12-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.37...@patternfly/react-code-editor@4.2.38) (2021-04-20) +# [5.2.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.34...@patternfly/react-code-editor@5.2.0-prerelease.35) (2023-12-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.33...@patternfly/react-code-editor@5.2.0-prerelease.34) (2023-12-07) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.32...@patternfly/react-code-editor@5.2.0-prerelease.33) (2023-12-06) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.36...@patternfly/react-code-editor@4.2.37) (2021-04-19) +# [5.2.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.31...@patternfly/react-code-editor@5.2.0-prerelease.32) (2023-11-21) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.30...@patternfly/react-code-editor@5.2.0-prerelease.31) (2023-11-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.29...@patternfly/react-code-editor@5.2.0-prerelease.30) (2023-11-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.35...@patternfly/react-code-editor@4.2.36) (2021-04-16) +# [5.2.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.28...@patternfly/react-code-editor@5.2.0-prerelease.29) (2023-11-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.27...@patternfly/react-code-editor@5.2.0-prerelease.28) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.26...@patternfly/react-code-editor@5.2.0-prerelease.27) (2023-11-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.34...@patternfly/react-code-editor@4.2.35) (2021-04-16) +# [5.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.25...@patternfly/react-code-editor@5.2.0-prerelease.26) (2023-11-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.24...@patternfly/react-code-editor@5.2.0-prerelease.25) (2023-11-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.23...@patternfly/react-code-editor@5.2.0-prerelease.24) (2023-11-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.33...@patternfly/react-code-editor@4.2.34) (2021-04-16) +# [5.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.22...@patternfly/react-code-editor@5.2.0-prerelease.23) (2023-11-03) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.21...@patternfly/react-code-editor@5.2.0-prerelease.22) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.20...@patternfly/react-code-editor@5.2.0-prerelease.21) (2023-11-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.32...@patternfly/react-code-editor@4.2.33) (2021-04-16) +# [5.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.19...@patternfly/react-code-editor@5.2.0-prerelease.20) (2023-11-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.18...@patternfly/react-code-editor@5.2.0-prerelease.19) (2023-10-30) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.17...@patternfly/react-code-editor@5.2.0-prerelease.18) (2023-10-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.31...@patternfly/react-code-editor@4.2.32) (2021-04-16) +# [5.2.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.16...@patternfly/react-code-editor@5.2.0-prerelease.17) (2023-10-27) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.15...@patternfly/react-code-editor@5.2.0-prerelease.16) (2023-10-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.14...@patternfly/react-code-editor@5.2.0-prerelease.15) (2023-10-26) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.30...@patternfly/react-code-editor@4.2.31) (2021-04-15) +# [5.2.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.13...@patternfly/react-code-editor@5.2.0-prerelease.14) (2023-10-23) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.12...@patternfly/react-code-editor@5.2.0-prerelease.13) (2023-10-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.11...@patternfly/react-code-editor@5.2.0-prerelease.12) (2023-10-18) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.29...@patternfly/react-code-editor@4.2.30) (2021-04-15) +# [5.2.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.10...@patternfly/react-code-editor@5.2.0-prerelease.11) (2023-10-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.9...@patternfly/react-code-editor@5.2.0-prerelease.10) (2023-10-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.8...@patternfly/react-code-editor@5.2.0-prerelease.9) (2023-10-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.28...@patternfly/react-code-editor@4.2.29) (2021-04-15) +# [5.2.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.7...@patternfly/react-code-editor@5.2.0-prerelease.8) (2023-10-16) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.6...@patternfly/react-code-editor@5.2.0-prerelease.7) (2023-10-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.5...@patternfly/react-code-editor@5.2.0-prerelease.6) (2023-10-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.27...@patternfly/react-code-editor@4.2.28) (2021-04-15) +# [5.2.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.4...@patternfly/react-code-editor@5.2.0-prerelease.5) (2023-10-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.3...@patternfly/react-code-editor@5.2.0-prerelease.4) (2023-10-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.2...@patternfly/react-code-editor@5.2.0-prerelease.3) (2023-10-10) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.26...@patternfly/react-code-editor@4.2.27) (2021-04-14) +# 5.2.0-prerelease.2 (2023-10-09) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.2.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.2.0-prerelease.0...@patternfly/react-code-editor@5.2.0-prerelease.1) (2023-10-09) +### Bug Fixes +- **CodeEditor:** hide button and link when read-only ([#9668](https://github.com/patternfly/patternfly-react/issues/9668)) ([0346933](https://github.com/patternfly/patternfly-react/commit/0346933cb61a3b11a2591acbde4760f58abffbcb)) - -## [4.2.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.25...@patternfly/react-code-editor@4.2.26) (2021-04-14) +# [5.2.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1...@patternfly/react-code-editor@5.2.0-prerelease.0) (2023-10-05) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.23...@patternfly/react-code-editor@5.1.1) (2023-10-05) +**Note:** Version bump only for package @patternfly/react-code-editor +## 5.1.1-prerelease.23 (2023-10-03) +### Bug Fixes -## [4.2.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.24...@patternfly/react-code-editor@4.2.25) (2021-04-13) - -**Note:** Version bump only for package @patternfly/react-code-editor +- whitespace changes to trigger prereleases ([#9702](https://github.com/patternfly/patternfly-react/issues/9702)) ([741c248](https://github.com/patternfly/patternfly-react/commit/741c24825b503e116c77cf304aa3e4e3a9ff7841)) +## [5.1.1-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.21...@patternfly/react-code-editor@5.1.1-prerelease.22) (2023-09-25) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.20...@patternfly/react-code-editor@5.1.1-prerelease.21) (2023-09-25) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.23...@patternfly/react-code-editor@4.2.24) (2021-04-13) +## [5.1.1-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.19...@patternfly/react-code-editor@5.1.1-prerelease.20) (2023-09-22) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.18...@patternfly/react-code-editor@5.1.1-prerelease.19) (2023-09-21) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.17...@patternfly/react-code-editor@5.1.1-prerelease.18) (2023-09-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.22...@patternfly/react-code-editor@4.2.23) (2021-04-12) +## [5.1.1-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.16...@patternfly/react-code-editor@5.1.1-prerelease.17) (2023-09-21) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.15...@patternfly/react-code-editor@5.1.1-prerelease.16) (2023-09-21) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.14...@patternfly/react-code-editor@5.1.1-prerelease.15) (2023-09-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.21...@patternfly/react-code-editor@4.2.22) (2021-04-09) +## [5.1.1-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.13...@patternfly/react-code-editor@5.1.1-prerelease.14) (2023-09-20) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.12...@patternfly/react-code-editor@5.1.1-prerelease.13) (2023-09-19) +### Bug Fixes +- **code-editor:** force element that wraps editor to be LTR ([#9626](https://github.com/patternfly/patternfly-react/issues/9626)) ([1c70d68](https://github.com/patternfly/patternfly-react/commit/1c70d6855fc5506bc2d683db91443219fa911189)) - -## [4.2.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.20...@patternfly/react-code-editor@4.2.21) (2021-04-08) +## [5.1.1-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.11...@patternfly/react-code-editor@5.1.1-prerelease.12) (2023-09-18) **Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.10...@patternfly/react-code-editor@5.1.1-prerelease.11) (2023-09-13) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.9...@patternfly/react-code-editor@5.1.1-prerelease.10) (2023-09-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.19...@patternfly/react-code-editor@4.2.20) (2021-04-05) +## [5.1.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.8...@patternfly/react-code-editor@5.1.1-prerelease.9) (2023-09-12) **Note:** Version bump only for package @patternfly/react-code-editor +## 5.1.1-prerelease.8 (2023-09-12) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.6...@patternfly/react-code-editor@5.1.1-prerelease.7) (2023-09-07) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.18...@patternfly/react-code-editor@4.2.19) (2021-04-05) +## [5.1.1-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.5...@patternfly/react-code-editor@5.1.1-prerelease.6) (2023-09-06) +**Note:** Version bump only for package @patternfly/react-code-editor -### Bug Fixes +## [5.1.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.4...@patternfly/react-code-editor@5.1.1-prerelease.5) (2023-09-05) -* **code-editor:** react peer dep ([#5618](https://github.com/patternfly/patternfly-react/issues/5618)) ([aef366d](https://github.com/patternfly/patternfly-react/commit/aef366da175a5cf560eca2168dd752d0f8fe4063)) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.3...@patternfly/react-code-editor@5.1.1-prerelease.4) (2023-09-01) +**Note:** Version bump only for package @patternfly/react-code-editor +## [5.1.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.1.1-prerelease.2...@patternfly/react-code-editor@5.1.1-prerelease.3) (2023-09-01) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.17...@patternfly/react-code-editor@4.2.18) (2021-04-01) +## 5.1.1-prerelease.2 (2023-08-31) **Note:** Version bump only for package @patternfly/react-code-editor +## 5.1.1-prerelease.1 (2023-08-29) +# 5.0.0 (2023-07-27) +**Note:** Version bump only for package @patternfly/react-code-editor - -## [4.2.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.16...@patternfly/react-code-editor@4.2.17) (2021-03-29) +# [5.1.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0...@patternfly/react-code-editor@5.1.0-prerelease.0) (2023-07-27) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0 (2023-07-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.26...@patternfly/react-code-editor@5.0.0-prerelease.27) (2023-07-26) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.15...@patternfly/react-code-editor@4.2.16) (2021-03-26) +# [5.0.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.25...@patternfly/react-code-editor@5.0.0-prerelease.26) (2023-07-24) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.24...@patternfly/react-code-editor@5.0.0-prerelease.25) (2023-07-20) +### Bug Fixes + +- **CodeEditor:** prevent clicks in textarea from opening fileupload ([#9385](https://github.com/patternfly/patternfly-react/issues/9385)) ([959bc7e](https://github.com/patternfly/patternfly-react/commit/959bc7ef2723bc3ef57db906ded7b1854b577eee)) +# 5.0.0-prerelease.24 (2023-07-20) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.14...@patternfly/react-code-editor@4.2.15) (2021-03-26) +# [5.0.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.22...@patternfly/react-code-editor@5.0.0-prerelease.23) (2023-07-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.21...@patternfly/react-code-editor@5.0.0-prerelease.22) (2023-07-13) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.20...@patternfly/react-code-editor@5.0.0-prerelease.21) (2023-07-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.13...@patternfly/react-code-editor@4.2.14) (2021-03-26) +# 5.0.0-prerelease.20 (2023-07-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.18...@patternfly/react-code-editor@5.0.0-prerelease.19) (2023-07-07) +**Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0-prerelease.18 (2023-07-06) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.12...@patternfly/react-code-editor@4.2.13) (2021-03-26) +# [5.0.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.16...@patternfly/react-code-editor@5.0.0-prerelease.17) (2023-07-06) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.15...@patternfly/react-code-editor@5.0.0-prerelease.16) (2023-07-06) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.14...@patternfly/react-code-editor@5.0.0-prerelease.15) (2023-06-30) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.11...@patternfly/react-code-editor@4.2.12) (2021-03-25) +# [5.0.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.13...@patternfly/react-code-editor@5.0.0-prerelease.14) (2023-06-30) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.12...@patternfly/react-code-editor@5.0.0-prerelease.13) (2023-06-21) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.11...@patternfly/react-code-editor@5.0.0-prerelease.12) (2023-06-21) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.10...@patternfly/react-code-editor@4.2.11) (2021-03-25) +# [5.0.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.10...@patternfly/react-code-editor@5.0.0-prerelease.11) (2023-06-15) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.9...@patternfly/react-code-editor@5.0.0-prerelease.10) (2023-06-15) + +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.8...@patternfly/react-code-editor@5.0.0-prerelease.9) (2023-06-13) +### Bug Fixes +- **docs:** update use of deprecated tag and clean up changelogs ([#9259](https://github.com/patternfly/patternfly-react/issues/9259)) ([8de83dc](https://github.com/patternfly/patternfly-react/commit/8de83dc3b2fb88094fd3c21bda2ed6e371986cba)) -## [4.2.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.9...@patternfly/react-code-editor@4.2.10) (2021-03-25) +# [5.0.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.7...@patternfly/react-code-editor@5.0.0-prerelease.8) (2023-06-12) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.6...@patternfly/react-code-editor@5.0.0-prerelease.7) (2023-06-12) +### Bug Fixes +- **react-icons:** Added fallback width and height attributes to icons ([#9257](https://github.com/patternfly/patternfly-react/issues/9257)) ([5c782ba](https://github.com/patternfly/patternfly-react/commit/5c782bacfdc02b907b2ca01a3a6800e2f6072b3e)) - -## [4.2.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.8...@patternfly/react-code-editor@4.2.9) (2021-03-24) +# [5.0.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.5...@patternfly/react-code-editor@5.0.0-prerelease.6) (2023-06-09) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.4...@patternfly/react-code-editor@5.0.0-prerelease.5) (2023-06-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.3...@patternfly/react-code-editor@5.0.0-prerelease.4) (2023-06-08) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.7...@patternfly/react-code-editor@4.2.8) (2021-03-22) +# [5.0.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.2...@patternfly/react-code-editor@5.0.0-prerelease.3) (2023-06-07) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-prerelease.1...@patternfly/react-code-editor@5.0.0-prerelease.2) (2023-06-06) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.133...@patternfly/react-code-editor@5.0.0-prerelease.1) (2023-06-06) +### Bug Fixes -## [4.2.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.6...@patternfly/react-code-editor@4.2.7) (2021-03-22) - -**Note:** Version bump only for package @patternfly/react-code-editor +- **release:** dryrun publishing prereleases ([#9242](https://github.com/patternfly/patternfly-react/issues/9242)) ([e4c35f1](https://github.com/patternfly/patternfly-react/commit/e4c35f14cd57be132179e51ae2bb223600a35f0e)) +# [5.0.0-alpha.133](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.132...@patternfly/react-code-editor@5.0.0-alpha.133) (2023-06-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.132](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.131...@patternfly/react-code-editor@5.0.0-alpha.132) (2023-06-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.5...@patternfly/react-code-editor@4.2.6) (2021-03-18) +# [5.0.0-alpha.131](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.130...@patternfly/react-code-editor@5.0.0-alpha.131) (2023-06-01) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.130](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.129...@patternfly/react-code-editor@5.0.0-alpha.130) (2023-06-01) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.129](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.128...@patternfly/react-code-editor@5.0.0-alpha.129) (2023-06-01) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.4...@patternfly/react-code-editor@4.2.5) (2021-03-17) +# [5.0.0-alpha.128](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.127...@patternfly/react-code-editor@5.0.0-alpha.128) (2023-05-31) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0-alpha.127 (2023-05-31) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.126](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.125...@patternfly/react-code-editor@5.0.0-alpha.126) (2023-05-31) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.3...@patternfly/react-code-editor@4.2.4) (2021-03-16) +# [5.0.0-alpha.125](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.124...@patternfly/react-code-editor@5.0.0-alpha.125) (2023-05-31) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.124](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.123...@patternfly/react-code-editor@5.0.0-alpha.124) (2023-05-31) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.123](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.122...@patternfly/react-code-editor@5.0.0-alpha.123) (2023-05-30) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.2...@patternfly/react-code-editor@4.2.3) (2021-03-16) +# [5.0.0-alpha.122](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.121...@patternfly/react-code-editor@5.0.0-alpha.122) (2023-05-30) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.121](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.120...@patternfly/react-code-editor@5.0.0-alpha.121) (2023-05-26) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.120](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.119...@patternfly/react-code-editor@5.0.0-alpha.120) (2023-05-25) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.1...@patternfly/react-code-editor@4.2.2) (2021-03-09) +# [5.0.0-alpha.119](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.118...@patternfly/react-code-editor@5.0.0-alpha.119) (2023-05-25) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.118](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.117...@patternfly/react-code-editor@5.0.0-alpha.118) (2023-05-25) +**Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0-alpha.117 (2023-05-23) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.2.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.2.0...@patternfly/react-code-editor@4.2.1) (2021-03-05) +# [5.0.0-alpha.116](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.115...@patternfly/react-code-editor@5.0.0-alpha.116) (2023-05-19) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.115](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.114...@patternfly/react-code-editor@5.0.0-alpha.115) (2023-05-18) + +### Bug Fixes +- **Multiple:** update old component classnames ([#9139](https://github.com/patternfly/patternfly-react/issues/9139)) ([8fbd940](https://github.com/patternfly/patternfly-react/commit/8fbd9401cd27cb84e73722292a2765781a46a6f7)) +# [5.0.0-alpha.114](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.113...@patternfly/react-code-editor@5.0.0-alpha.114) (2023-05-18) +**Note:** Version bump only for package @patternfly/react-code-editor -# [4.2.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.34...@patternfly/react-code-editor@4.2.0) (2021-03-05) +# [5.0.0-alpha.113](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.112...@patternfly/react-code-editor@5.0.0-alpha.113) (2023-05-18) +**Note:** Version bump only for package @patternfly/react-code-editor -### Features +# [5.0.0-alpha.112](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.111...@patternfly/react-code-editor@5.0.0-alpha.112) (2023-05-18) -* **CodeEditor:** Make 'code' prop controlled ([#5465](https://github.com/patternfly/patternfly-react/issues/5465)) ([613dec6](https://github.com/patternfly/patternfly-react/commit/613dec6d46ed0c08bc9e445a0a16bf6b6bb56bd1)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.111](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.110...@patternfly/react-code-editor@5.0.0-alpha.111) (2023-05-18) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.110](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.109...@patternfly/react-code-editor@5.0.0-alpha.110) (2023-05-18) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.33...@patternfly/react-code-editor@4.1.34) (2021-03-04) +# [5.0.0-alpha.109](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.108...@patternfly/react-code-editor@5.0.0-alpha.109) (2023-05-18) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.108](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.107...@patternfly/react-code-editor@5.0.0-alpha.108) (2023-05-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.107](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.106...@patternfly/react-code-editor@5.0.0-alpha.107) (2023-05-17) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.32...@patternfly/react-code-editor@4.1.33) (2021-03-04) +# [5.0.0-alpha.106](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.105...@patternfly/react-code-editor@5.0.0-alpha.106) (2023-05-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.105](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.104...@patternfly/react-code-editor@5.0.0-alpha.105) (2023-05-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.104](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.103...@patternfly/react-code-editor@5.0.0-alpha.104) (2023-05-17) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.31...@patternfly/react-code-editor@4.1.32) (2021-03-04) +# [5.0.0-alpha.103](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.102...@patternfly/react-code-editor@5.0.0-alpha.103) (2023-05-16) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.102](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.101...@patternfly/react-code-editor@5.0.0-alpha.102) (2023-05-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.101](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.100...@patternfly/react-code-editor@5.0.0-alpha.101) (2023-05-16) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.30...@patternfly/react-code-editor@4.1.31) (2021-03-03) +# [5.0.0-alpha.100](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.99...@patternfly/react-code-editor@5.0.0-alpha.100) (2023-05-15) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.99](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.98...@patternfly/react-code-editor@5.0.0-alpha.99) (2023-05-11) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.98](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.97...@patternfly/react-code-editor@5.0.0-alpha.98) (2023-05-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.29...@patternfly/react-code-editor@4.1.30) (2021-03-03) +# [5.0.0-alpha.97](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.96...@patternfly/react-code-editor@5.0.0-alpha.97) (2023-05-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.96](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.95...@patternfly/react-code-editor@5.0.0-alpha.96) (2023-05-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.95](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.94...@patternfly/react-code-editor@5.0.0-alpha.95) (2023-05-09) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.28...@patternfly/react-code-editor@4.1.29) (2021-03-02) +# 5.0.0-alpha.94 (2023-05-08) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.93](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.92...@patternfly/react-code-editor@5.0.0-alpha.93) (2023-05-08) +**Note:** Version bump only for package @patternfly/react-code-editor + +# [5.0.0-alpha.92](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.91...@patternfly/react-code-editor@5.0.0-alpha.92) (2023-05-05) +### Bug Fixes +- **deps:** updated Core for v5 versioning ([#9075](https://github.com/patternfly/patternfly-react/issues/9075)) ([3879fc7](https://github.com/patternfly/patternfly-react/commit/3879fc757aefeed80b0694365aa20d5ca856a797)) -## [4.1.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.27...@patternfly/react-code-editor@4.1.28) (2021-03-02) +# [5.0.0-alpha.91](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.90...@patternfly/react-code-editor@5.0.0-alpha.91) (2023-05-05) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0-alpha.90 (2023-05-04) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.89](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.88...@patternfly/react-code-editor@5.0.0-alpha.89) (2023-05-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.26...@patternfly/react-code-editor@4.1.27) (2021-02-24) +# [5.0.0-alpha.88](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.87...@patternfly/react-code-editor@5.0.0-alpha.88) (2023-05-03) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.87](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.86...@patternfly/react-code-editor@5.0.0-alpha.87) (2023-05-03) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.86](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.85...@patternfly/react-code-editor@5.0.0-alpha.86) (2023-05-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.25...@patternfly/react-code-editor@4.1.26) (2021-02-18) +# [5.0.0-alpha.85](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.84...@patternfly/react-code-editor@5.0.0-alpha.85) (2023-05-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.84](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.83...@patternfly/react-code-editor@5.0.0-alpha.84) (2023-04-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.83](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.82...@patternfly/react-code-editor@5.0.0-alpha.83) (2023-04-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.24...@patternfly/react-code-editor@4.1.25) (2021-02-17) +# [5.0.0-alpha.82](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.81...@patternfly/react-code-editor@5.0.0-alpha.82) (2023-04-27) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.81](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.80...@patternfly/react-code-editor@5.0.0-alpha.81) (2023-04-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.80](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.79...@patternfly/react-code-editor@5.0.0-alpha.80) (2023-04-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.23...@patternfly/react-code-editor@4.1.24) (2021-02-16) +# [5.0.0-alpha.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.78...@patternfly/react-code-editor@5.0.0-alpha.79) (2023-04-26) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.77...@patternfly/react-code-editor@5.0.0-alpha.78) (2023-04-25) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.76...@patternfly/react-code-editor@5.0.0-alpha.77) (2023-04-25) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.22...@patternfly/react-code-editor@4.1.23) (2021-02-12) +# [5.0.0-alpha.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.75...@patternfly/react-code-editor@5.0.0-alpha.76) (2023-04-24) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.74...@patternfly/react-code-editor@5.0.0-alpha.75) (2023-04-20) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.73...@patternfly/react-code-editor@5.0.0-alpha.74) (2023-04-19) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.21...@patternfly/react-code-editor@4.1.22) (2021-02-12) +# [5.0.0-alpha.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.72...@patternfly/react-code-editor@5.0.0-alpha.73) (2023-04-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.71...@patternfly/react-code-editor@5.0.0-alpha.72) (2023-04-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.70...@patternfly/react-code-editor@5.0.0-alpha.71) (2023-04-14) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.20...@patternfly/react-code-editor@4.1.21) (2021-02-11) +# [5.0.0-alpha.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.69...@patternfly/react-code-editor@5.0.0-alpha.70) (2023-04-14) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.68...@patternfly/react-code-editor@5.0.0-alpha.69) (2023-04-13) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.67...@patternfly/react-code-editor@5.0.0-alpha.68) (2023-04-13) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.19...@patternfly/react-code-editor@4.1.20) (2021-02-11) +# [5.0.0-alpha.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.66...@patternfly/react-code-editor@5.0.0-alpha.67) (2023-04-13) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.65...@patternfly/react-code-editor@5.0.0-alpha.66) (2023-04-12) +**Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0-alpha.65 (2023-04-12) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.18...@patternfly/react-code-editor@4.1.19) (2021-02-11) +# [5.0.0-alpha.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.63...@patternfly/react-code-editor@5.0.0-alpha.64) (2023-04-11) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.62...@patternfly/react-code-editor@5.0.0-alpha.63) (2023-04-11) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.61...@patternfly/react-code-editor@5.0.0-alpha.62) (2023-04-11) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.17...@patternfly/react-code-editor@4.1.18) (2021-02-11) +# 5.0.0-alpha.61 (2023-04-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.59...@patternfly/react-code-editor@5.0.0-alpha.60) (2023-04-07) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.58...@patternfly/react-code-editor@5.0.0-alpha.59) (2023-04-06) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.16...@patternfly/react-code-editor@4.1.17) (2021-02-11) +# [5.0.0-alpha.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.57...@patternfly/react-code-editor@5.0.0-alpha.58) (2023-04-05) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.56...@patternfly/react-code-editor@5.0.0-alpha.57) (2023-04-05) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.55...@patternfly/react-code-editor@5.0.0-alpha.56) (2023-04-05) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.15...@patternfly/react-code-editor@4.1.16) (2021-02-10) +# [5.0.0-alpha.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.54...@patternfly/react-code-editor@5.0.0-alpha.55) (2023-04-05) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.53...@patternfly/react-code-editor@5.0.0-alpha.54) (2023-04-05) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.52...@patternfly/react-code-editor@5.0.0-alpha.53) (2023-04-04) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.14...@patternfly/react-code-editor@4.1.15) (2021-02-10) +# [5.0.0-alpha.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.51...@patternfly/react-code-editor@5.0.0-alpha.52) (2023-04-03) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.50...@patternfly/react-code-editor@5.0.0-alpha.51) (2023-03-27) +**Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0-alpha.50 (2023-03-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.13...@patternfly/react-code-editor@4.1.14) (2021-02-10) +# [5.0.0-alpha.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.48...@patternfly/react-code-editor@5.0.0-alpha.49) (2023-03-24) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.47...@patternfly/react-code-editor@5.0.0-alpha.48) (2023-03-24) + +### Bug Fixes +- **CodeEditor:** fix typo in README ([#8849](https://github.com/patternfly/patternfly-react/issues/8849)) ([4579484](https://github.com/patternfly/patternfly-react/commit/4579484257d866e75b22325349f19940fb17c631)) +# [5.0.0-alpha.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.46...@patternfly/react-code-editor@5.0.0-alpha.47) (2023-03-24) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.12...@patternfly/react-code-editor@4.1.13) (2021-02-10) +# [5.0.0-alpha.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.45...@patternfly/react-code-editor@5.0.0-alpha.46) (2023-03-24) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.44...@patternfly/react-code-editor@5.0.0-alpha.45) (2023-03-23) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.43...@patternfly/react-code-editor@5.0.0-alpha.44) (2023-03-23) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.11...@patternfly/react-code-editor@4.1.12) (2021-02-10) +# [5.0.0-alpha.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.42...@patternfly/react-code-editor@5.0.0-alpha.43) (2023-03-22) **Note:** Version bump only for package @patternfly/react-code-editor +# 5.0.0-alpha.42 (2023-03-21) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.40...@patternfly/react-code-editor@5.0.0-alpha.41) (2023-03-20) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.10...@patternfly/react-code-editor@4.1.11) (2021-02-08) +# [5.0.0-alpha.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.39...@patternfly/react-code-editor@5.0.0-alpha.40) (2023-03-18) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.38...@patternfly/react-code-editor@5.0.0-alpha.39) (2023-03-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.37...@patternfly/react-code-editor@5.0.0-alpha.38) (2023-03-17) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.9...@patternfly/react-code-editor@4.1.10) (2021-02-03) +# [5.0.0-alpha.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.36...@patternfly/react-code-editor@5.0.0-alpha.37) (2023-03-17) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.35...@patternfly/react-code-editor@5.0.0-alpha.36) (2023-03-17) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.34...@patternfly/react-code-editor@5.0.0-alpha.35) (2023-03-15) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.8...@patternfly/react-code-editor@4.1.9) (2021-02-03) +# [5.0.0-alpha.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.33...@patternfly/react-code-editor@5.0.0-alpha.34) (2023-03-15) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.32...@patternfly/react-code-editor@5.0.0-alpha.33) (2023-03-13) +- EmptyState component cleanup to match core implementation (#8737) ([40dd9ad](https://github.com/patternfly/patternfly-react/commit/40dd9ad4b2ab32887c2f72a10eb78f2c4ee5ac4b)), closes [#8737](https://github.com/patternfly/patternfly-react/issues/8737) [#8555](https://github.com/patternfly/patternfly-react/issues/8555) +### BREAKING CHANGES +- closes #8555, fixes #8455 -## [4.1.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.7...@patternfly/react-code-editor@4.1.8) (2021-02-02) +- docs(EmptyState): updated examples +updated examples of EmptyState usage on the PatternFly web to use new API -### Bug Fixes +# [5.0.0-alpha.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.31...@patternfly/react-code-editor@5.0.0-alpha.32) (2023-03-13) -* **codeeditor:** copy to clipboard button can now be enabled solo 🥰 ([#5411](https://github.com/patternfly/patternfly-react/issues/5411)) ([c409239](https://github.com/patternfly/patternfly-react/commit/c409239f408f57dbd2cef7ac8482321de1abf947)) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.30...@patternfly/react-code-editor@5.0.0-alpha.31) (2023-03-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.29...@patternfly/react-code-editor@5.0.0-alpha.30) (2023-03-09) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.6...@patternfly/react-code-editor@4.1.7) (2021-02-02) +# [5.0.0-alpha.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.28...@patternfly/react-code-editor@5.0.0-alpha.29) (2023-03-09) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.27...@patternfly/react-code-editor@5.0.0-alpha.28) (2023-03-09) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.26...@patternfly/react-code-editor@5.0.0-alpha.27) (2023-03-08) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.5...@patternfly/react-code-editor@4.1.6) (2021-02-01) +# [5.0.0-alpha.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.25...@patternfly/react-code-editor@5.0.0-alpha.26) (2023-03-07) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.24...@patternfly/react-code-editor@5.0.0-alpha.25) (2023-03-04) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.23...@patternfly/react-code-editor@5.0.0-alpha.24) (2023-03-03) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.4...@patternfly/react-code-editor@4.1.5) (2021-02-01) +# [5.0.0-alpha.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.22...@patternfly/react-code-editor@5.0.0-alpha.23) (2023-03-03) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.21...@patternfly/react-code-editor@5.0.0-alpha.22) (2023-03-02) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.20...@patternfly/react-code-editor@5.0.0-alpha.21) (2023-03-02) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.3...@patternfly/react-code-editor@4.1.4) (2021-01-27) +# 5.0.0-alpha.20 (2023-03-02) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.18...@patternfly/react-code-editor@5.0.0-alpha.19) (2023-03-01) +**Note:** Version bump only for package @patternfly/react-code-editor + +# [5.0.0-alpha.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.17...@patternfly/react-code-editor@5.0.0-alpha.18) (2023-03-01) +### Features +- **Checkbox:** changed order of onChange params ([#8750](https://github.com/patternfly/patternfly-react/issues/8750)) ([0a87f55](https://github.com/patternfly/patternfly-react/commit/0a87f554e4cf3abb99de8f2ccd53737f0cf489b1)) -## [4.1.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.2...@patternfly/react-code-editor@4.1.3) (2021-01-26) +# [5.0.0-alpha.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.16...@patternfly/react-code-editor@5.0.0-alpha.17) (2023-03-01) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.15...@patternfly/react-code-editor@5.0.0-alpha.16) (2023-02-28) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.14...@patternfly/react-code-editor@5.0.0-alpha.15) (2023-02-27) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.1...@patternfly/react-code-editor@4.1.2) (2021-01-25) +# 5.0.0-alpha.14 (2023-02-22) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.12...@patternfly/react-code-editor@5.0.0-alpha.13) (2023-02-16) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.11...@patternfly/react-code-editor@5.0.0-alpha.12) (2023-02-15) +**Note:** Version bump only for package @patternfly/react-code-editor -## [4.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@4.1.0...@patternfly/react-code-editor@4.1.1) (2021-01-25) +# [5.0.0-alpha.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.10...@patternfly/react-code-editor@5.0.0-alpha.11) (2023-02-10) **Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.9...@patternfly/react-code-editor@5.0.0-alpha.10) (2023-02-10) +**Note:** Version bump only for package @patternfly/react-code-editor +# [5.0.0-alpha.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.8...@patternfly/react-code-editor@5.0.0-alpha.9) (2023-02-09) +**Note:** Version bump only for package @patternfly/react-code-editor -# 4.1.0 (2021-01-25) +# [5.0.0-alpha.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.7...@patternfly/react-code-editor@5.0.0-alpha.8) (2023-02-08) +**Note:** Version bump only for package @patternfly/react-code-editor -### Features +# [5.0.0-alpha.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-code-editor@5.0.0-alpha.6...@patternfly/react-code-editor@5.0.0-alpha.7) (2023-02-08) -* **CodeEditor:** add new code editor ([#5294](https://github.com/patternfly/patternfly-react/issues/5294)) ([1c36ce3](https://github.com/patternfly/patternfly-react/commit/1c36ce36912e146f28a998e861ff8887f3ff9eb1)) +**Note:** Version bump only for package @patternfly/react-code-editor diff --git a/packages/react-code-editor/README.md b/packages/react-code-editor/README.md index 963d9c2e133..b488240a459 100644 --- a/packages/react-code-editor/README.md +++ b/packages/react-code-editor/README.md @@ -1,32 +1,41 @@ # @patternfly/react-code-editor -This package provides a PatternFly wrapper for the Monaco code editor +This package provides a PatternFly wrapper for the Monaco code editor, using the `@monaco-editor/react` package. -### Prerequisite - -#### Node Environment +### Installing -This project currently supports Node [Active LTS](https://github.com/nodejs/Release#release-schedule) releases. Please stay current with Node Active LTS when developing patternfly-react. +```sh +yarn add @patternfly/react-code-editor +``` -For example, to develop with Node 8, use the following: +or +```sh +npm install @patternfly/react-code-editor ``` -nvm install 8 -nvm use 8 + +[!NOTE] For TypeScript type definitions, this package uses the `monaco-editor` package as a peer dependency. So, if you need types and don't already have the `monaco-editor` package installed, you will need to do so: + +```sh +yarn add --dev monaco-editor ``` -This project also requires a Yarn version of >=1.6.0. The latest version can be installed [here](https://yarnpkg.com/). +or -### Installing +```sh +npm install --dev monaco-editor +``` + +[!NOTE] For TypeScript type definitions, this package uses the `monaco-editor` package as a peer dependency. So, if you need types and don't already have the `monaco-editor package` installed, you will need to do so: ``` -yarn add @patternfly/react-code-editor +yarn add --dev monaco-editor ``` or ``` -npm install @patternfly/react-code-editor --save +npm install --dev monaco-editor ``` ### Usage @@ -43,11 +52,73 @@ import '@patternfly/react-core/dist/styles/base.css'; import { CodeEditor } from '@patternfly/react-code-editor'; ``` -Install peer deps +#### With create-react-app Projects + +If you created your project with `create-react-app` you'll have some extra work to do, or you wont have syntax highlighting. Using the webpack plugin requires updating your webpack config, which `create-react-app` abstracts away. You can `npm eject` your project, but you may not want to do that. To keep your app set up in the `create-react-app` style but to get access to your webpack config you can use `react-app-rewired`. + +First, install `react-app-rewired` as a development dependency: + +```sh +$ npm install -D react-app-rewired +``` + +Next, replace all of the `react-script` references in your `package.json` `scripts` section with `react-app-required`: + ```json -"monaco-editor": "^0.21.3", -"monaco-editor-webpack-plugin": "^2.1.0", -"react": "^16.8.0 || ^17.0.0", -"react-dom": "^16.8.0 || ^17.0.0", -"react-monaco-editor": "^0.41.2" + "scripts": { + "start": "react-app-rewired start", + "build": "react-app-rewired build", + "test": "react-app-rewired test", + "eject": "react-app-rewired eject" + } +``` + +You can now start your app with `npm start` and syntax highlighting should work. + +#### To use monaco-editor as an npm package and avoid using CDN + +The `@monaco-editor/react` package is built on the `monaco-editor` package, which will fetch some additional files using CDN by default. To avoid this, include `monaco-editor` as a dependency and insert the following into your code: + +``` +import * as monaco from 'monaco-editor'; +import { loader } from '@monaco-editor/react'; + +loader.config({ monaco }); +``` + +This may require the additonal `webpack` plugins such as `monaco-editor-webpack-plugin`. To properly install the library `monaco-editor-webpack-plugin` be sure to follow the [plugin instructions](https://github.com/microsoft/monaco-editor/tree/main/webpack-plugin) + +#### Enable YAML Syntax Highlighting + +The Monaco editor doesn't ship with full YAML support. You can configure your code editor with `Languages.yaml` but there will be no highlighting. To enable YAML support you need to do the following: + +First, install `monaco-yaml`: + +```shell +$ npm install --save monaco-yaml +``` + +Next, at the entrypoint of your app enable it: + +```javascript +import { setDiagnosticsOptions } from 'monaco-yaml'; + +setDiagnosticsOptions({ + enableSchemaRequest: true, + hover: true, + completion: true, + validate: true, + format: true, + schemas: [] +}); ``` + +Finally, to allow the `monaco-yaml` autocomplete to function properly with `@monaco-editor/react`, you should configure your YAML schema in a `beforeMount` call with the `monaco-yaml` `configureMonacoYaml` function. This `beforeMount` function should be passed to `CodeEditor` via the `editorProps` property like so: + +``` +editorProps: { + beforeMount: yourBeforeMountHandler +} +``` + +The `monaco-yaml` plugin has a lot of options so check out their docs to see what else you may want to add. diff --git a/packages/react-code-editor/package.json b/packages/react-code-editor/package.json index a60a9accecf..d07a193cd3e 100644 --- a/packages/react-code-editor/package.json +++ b/packages/react-code-editor/package.json @@ -1,6 +1,6 @@ { "name": "@patternfly/react-code-editor", - "version": "4.29.0", + "version": "6.6.0-prerelease.1", "description": "This package provides a PatternFly wrapper for the Monaco code editor\n", "main": "dist/js/index.js", "module": "dist/esm/index.js", @@ -30,20 +30,18 @@ "clean": "rimraf dist" }, "dependencies": { - "@patternfly/react-core": "^4.188.0", - "@patternfly/react-icons": "^4.39.0", - "@patternfly/react-styles": "^4.38.0", - "react-dropzone": "9.0.0", - "tslib": "^2.0.0" + "@monaco-editor/react": "^4.7.0", + "@patternfly/react-core": "workspace:^", + "@patternfly/react-icons": "workspace:^", + "@patternfly/react-styles": "workspace:^", + "react-dropzone": "14.3.5", + "tslib": "^2.8.1" }, "peerDependencies": { - "monaco-editor-webpack-plugin": "^2.1.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0", - "react-monaco-editor": "^0.41.2" + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" }, "devDependencies": { - "rimraf": "^2.6.2", - "typescript": "^4.0.0" + "monaco-editor": "^0.55.1" } } diff --git a/packages/react-code-editor/src/components/CodeEditor/CodeEditor.tsx b/packages/react-code-editor/src/components/CodeEditor/CodeEditor.tsx index 2466b57a188..ac3ac11aec6 100644 --- a/packages/react-code-editor/src/components/CodeEditor/CodeEditor.tsx +++ b/packages/react-code-editor/src/components/CodeEditor/CodeEditor.tsx @@ -1,25 +1,38 @@ -import * as React from 'react'; +import { HTMLProps, ReactNode, useEffect, useRef, useState } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/CodeEditor/code-editor'; +import fileUploadStyles from '@patternfly/react-styles/css/components/FileUpload/file-upload'; +import monoFont from '@patternfly/react-tokens/dist/esm/t_global_font_family_mono'; +import { Button, ButtonVariant } from '@patternfly/react-core/dist/esm/components/Button'; import { - Button, EmptyState, + EmptyStateActions, EmptyStateBody, - EmptyStateIcon, - EmptyStateSecondaryActions, - EmptyStateVariant, - getResizeObserver, - Title, - Tooltip -} from '@patternfly/react-core'; -import MonacoEditor, { ChangeHandler, EditorDidMount } from 'react-monaco-editor'; -import { editor } from 'monaco-editor/esm/vs/editor/editor.api'; + EmptyStateFooter, + EmptyStateVariant +} from '@patternfly/react-core/dist/esm/components/EmptyState'; +import { Popover, PopoverProps } from '@patternfly/react-core/dist/esm/components/Popover'; +import { TooltipPosition } from '@patternfly/react-core/dist/esm/components/Tooltip'; +import { getResizeObserver } from '@patternfly/react-core/dist/esm/helpers/resizeObserver'; +import Editor, { BeforeMount, EditorProps, Monaco } from '@monaco-editor/react'; +import type { editor } from 'monaco-editor'; import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon'; import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon'; -import Dropzone from 'react-dropzone'; +import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; +import Dropzone, { FileRejection } from 'react-dropzone'; import { CodeEditorContext } from './CodeEditorUtils'; +import { CodeEditorControl } from './CodeEditorControl'; +import { defineThemes } from './CodeEditorTheme'; + +export type ChangeHandler = (value: string, event: editor.IModelContentChangedEvent) => void; +export type EditorDidMount = (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => void; + +export interface Shortcut { + description: string; + keys: string[]; +} export enum Language { abap = 'abap', @@ -99,484 +112,528 @@ export enum Language { yaml = 'yaml' } -export interface CodeEditorProps extends Omit, 'onChange'> { - /** additional classes added to the code editor */ +/** The main code editor component. */ + +export interface CodeEditorProps extends Omit, 'onChange'> { + /** Additional classes added to the code editor. */ className?: string; - /** code displayed in code editor */ + /** Code displayed in code editor. */ code?: string; - /** language displayed in the editor */ - language?: Language; - /** Flag indicating the editor is styled using monaco's dark theme */ - isDarkTheme?: boolean; - /** Width of code editor. Defaults to 100% */ - width?: string; - /** Flag indicating the editor is displaying line numbers */ - isLineNumbersVisible?: boolean; - /** Flag indicating the editor is read only */ - isReadOnly?: boolean; - /** Height of code editor. Defaults to 100% */ - height?: string; - /** Function which fires each time the code changes in the code editor */ - onChange?: ChangeHandler; - /** The loading screen before the editor will be loaded. Defaults 'loading...' */ - loading?: React.ReactNode; - /** Content to display in space of the code editor when there is no code to display */ - emptyState?: React.ReactNode; - /** Override default empty state title text */ - emptyStateTitle?: React.ReactNode; - /** Override default empty state body text */ - emptyStateBody?: React.ReactNode; - /** Override default empty state title text */ - emptyStateButton?: React.ReactNode; - /** Override default empty state body text */ - emptyStateLink?: React.ReactNode; - /** Name of the file if user downloads code to local file */ - downloadFileName?: string; - /** Flag to add upload button to code editor actions. Also makes the code editor accept a file using drag and drop */ - isUploadEnabled?: boolean; - /** Flag to add download button to code editor actions */ - isDownloadEnabled?: boolean; - /** Flag to add copy button to code editor actions */ - isCopyEnabled?: boolean; - /** Flag to include a label indicating the currently configured editor language */ - isLanguageLabelVisible?: boolean; - /** Accessibly label for the copy button */ + /** Accessible label for the copy button. */ copyButtonAriaLabel?: string; - /** Text to display in the tooltip on the copy button before text is copied */ - copyButtonToolTipText?: string; - /** Text to display in the tooltip on the copy button after code copied to clipboard */ + /** Text to display in the tooltip on the copy button after code is copied to clipboard. */ copyButtonSuccessTooltipText?: string; - /** Accessible label for the upload button */ - uploadButtonAriaLabel?: string; - /** Text to display in the tooltip on the upload button */ - uploadButtonToolTipText?: string; - /** Accessible label for the download button */ + /** Text to display in the tooltip on the copy button before code is copied. */ + copyButtonToolTipText?: string; + /** A single node or array of nodes - ideally the code editor controls component - to display + * above code editor. + */ + customControls?: ReactNode | ReactNode[]; + /** Accessible label for the download button. */ downloadButtonAriaLabel?: string; - /** Text to display in the tooltip on the download button */ + /** Text to display in the tooltip on the download button. */ downloadButtonToolTipText?: string; - /** The delay before tooltip fades after code copied */ - toolTipCopyExitDelay: number; - /** The entry and exit delay for all tooltips */ - toolTipDelay: number; - /** The max width of the tooltips on all button */ - toolTipMaxWidth: string; - /** The position of tooltips on all buttons */ - toolTipPosition: 'auto' | 'top' | 'bottom' | 'left' | 'right'; - /** A single node or array of nodes - ideally CodeEditorControls - to display above code editor */ - customControls?: React.ReactNode | React.ReactNode[]; - /** Callback which fires after the code editor is mounted containing - * a reference to the monaco editor and the monaco instance */ - onEditorDidMount?: EditorDidMount; - /** Flag to add the minimap to the code editor */ + /** Name of the file if user downloads code to local file. */ + downloadFileName?: string; + /** Additional props to pass to the monaco editor. */ + editorProps?: EditorProps; + /** Content to display in space of the code editor when there is no code to display. */ + emptyState?: ReactNode; + /** Override default empty state body text. */ + emptyStateBody?: ReactNode; + /** Override default empty state button text. */ + emptyStateButton?: ReactNode; + /** Override default empty state link text. */ + emptyStateLink?: ReactNode; + /** Override default empty state title text. */ + emptyStateTitle?: ReactNode; + /** Editor header main content title. */ + headerMainContent?: string; + /** Height of code editor. 'sizeToFit' will automatically change the height + * to the height of the content. + */ + height?: string | 'sizeToFit'; + /** Flag to add copy button to code editor actions. */ + isCopyEnabled?: boolean; + /** Flag indicating the editor is styled using monaco's dark theme. */ + isDarkTheme?: boolean; + /** Flag that enables component to consume the available height of its container. If `height` prop is set to 100%, this will also become enabled. */ + isFullHeight?: boolean; + /** Flag indicating the editor has a plain header. */ + isHeaderPlain?: boolean; + /** Flag to add download button to code editor actions. */ + isDownloadEnabled?: boolean; + /** Flag to include a label indicating the currently configured editor language. */ + isLanguageLabelVisible?: boolean; + /** Flag indicating the editor is displaying line numbers. */ + isLineNumbersVisible?: boolean; + /** Flag to add the minimap to the code editor. */ isMinimapVisible?: boolean; - /** Flag to show the editor */ - showEditor?: boolean; - /** - * Refer to Monaco interface {monaco.editor.IStandaloneEditorConstructionOptions}. + /** Flag indicating the editor is read only. */ + isReadOnly?: boolean; + /** Flag to add upload button to code editor actions. Also makes the code editor accept a + * file using drag and drop. */ + isUploadEnabled?: boolean; + /** Language displayed in the editor. */ + language?: Language; + /** The loading screen before the editor will be loaded. Defaults to 'loading...'. */ + loading?: ReactNode; + /** Function which fires each time the content of the code editor is manually changed. Does + * not fire when a file is uploaded. */ - options?: editor.IStandaloneEditorConstructionOptions; - /** - * Refer to Monaco interface {monaco.editor.IEditorOverrideServices}. + onChange?: ChangeHandler; + /** Function which fires each time the code changes in the code editor. */ + onCodeChange?: (value: string) => void; + /** Function which fires when the code is downloaded. Defaults to a function that + * downloads the current editor content. */ + onDownload?: (value: string, fileName: string) => void; + /** Callback which fires after the code editor is mounted containing a reference to the + * monaco editor and the monaco instance. */ + onEditorDidMount?: EditorDidMount; + /** Refer to Monaco interface {monaco.editor.IStandaloneEditorConstructionOptions}. */ + options?: editor.IStandaloneEditorConstructionOptions; + /** Refer to Monaco interface {monaco.editor.IEditorOverrideServices}. */ overrideServices?: editor.IEditorOverrideServices; + /** Text to show in the button to open the shortcut popover. */ + shortcutsPopoverButtonText?: string; + /** Properties for the shortcut popover. */ + shortcutsPopoverProps?: PopoverProps; + /** Flag to show the editor. */ + showEditor?: boolean; + /** The delay before tooltip fades after code copied. */ + toolTipCopyExitDelay?: number; + /** The entry and exit delay for all tooltips. */ + toolTipDelay?: number; + /** The max width of the tooltips on all button. */ + toolTipMaxWidth?: string; + /** The position of tooltips on all buttons. */ + toolTipPosition?: + | TooltipPosition + | 'auto' + | 'top' + | 'bottom' + | 'left' + | 'right' + | 'top-start' + | 'top-end' + | 'bottom-start' + | 'bottom-end' + | 'left-start' + | 'left-end' + | 'right-start' + | 'right-end'; + /** Accessible label for the upload button. */ + uploadButtonAriaLabel?: string; + /** Text to display in the tooltip on the upload button. */ + uploadButtonToolTipText?: string; + /** Width of code editor. Defaults to 100%. */ + width?: string; } -interface CodeEditorState { - value: string; - filename: string; - isLoading: boolean; - showEmptyState: boolean; - copied: boolean; -} +const getExtensionFromLanguage = (language: Language) => { + switch (language) { + case Language.shell: + return 'sh'; + case Language.ruby: + return 'rb'; + case Language.perl: + return 'pl'; + case Language.python: + return 'py'; + case Language.mysql: + return 'sql'; + case Language.javascript: + return 'js'; + case Language.typescript: + return 'ts'; + case Language.markdown: + return 'md'; + case Language.plaintext: + return 'txt'; + default: + return language.toString(); + } +}; -export class CodeEditor extends React.Component { - static displayName = 'CodeEditor'; - private editor: editor.IStandaloneCodeEditor | null = null; - private wrapperRef = React.createRef(); - private ref = React.createRef(); - private timer: number | null = null; - private observer = () => {}; - - static defaultProps: CodeEditorProps = { - className: '', - code: '', - onEditorDidMount: () => {}, - language: Language.plaintext, - isDarkTheme: false, - height: '', - width: '', - isLineNumbersVisible: true, - isReadOnly: false, - isLanguageLabelVisible: false, - loading: '', - emptyState: '', - emptyStateTitle: 'Start editing', - emptyStateBody: 'Drag and drop a file or upload one.', - emptyStateButton: 'Browse', - emptyStateLink: 'Start from scratch', - downloadFileName: Date.now().toString(), - isUploadEnabled: false, - isDownloadEnabled: false, - isCopyEnabled: false, - copyButtonAriaLabel: 'Copy code to clipboard', - uploadButtonAriaLabel: 'Upload code', - downloadButtonAriaLabel: 'Download code', - copyButtonToolTipText: 'Copy to clipboard', - uploadButtonToolTipText: 'Upload', - downloadButtonToolTipText: 'Download', - copyButtonSuccessTooltipText: 'Content added to clipboard', - toolTipCopyExitDelay: 1600, - toolTipDelay: 300, - toolTipMaxWidth: '100px', - toolTipPosition: 'top', - customControls: null, - isMinimapVisible: false, - showEditor: true, - options: {}, - overrideServices: {} - }; +/** + * Downloads a file to a users device given its string content and a full file name. + */ +const defaultOnDownload = (value: string, fileName: string) => { + const link = document.createElement('a'); + link.href = URL.createObjectURL(new Blob([value], { type: 'text' })); + link.download = fileName; + link.click(); +}; - static getExtensionFromLanguage(language: Language) { - switch (language) { - case Language.shell: - return 'sh'; - case Language.ruby: - return 'rb'; - case Language.perl: - return 'pl'; - case Language.python: - return 'py'; - case Language.mysql: - return 'sql'; - case Language.javascript: - return 'js'; - case Language.typescript: - return 'ts'; - case Language.markdown: - return 'md'; - case Language.plaintext: - return 'txt'; - default: - return language.toString(); - } - } +export const CodeEditor = ({ + className = '', + code = '', + copyButtonAriaLabel = 'Copy code to clipboard', + copyButtonSuccessTooltipText = 'Content added to clipboard', + copyButtonToolTipText = 'Copy to clipboard', + customControls = null, + downloadButtonAriaLabel = 'Download code', + downloadButtonToolTipText = 'Download', + downloadFileName = Date.now().toString(), + editorProps, + emptyState = '', + emptyStateBody = 'Drag and drop a file or upload one.', + emptyStateButton = 'Browse', + emptyStateLink = 'Start from scratch', + emptyStateTitle = 'Start editing', + headerMainContent = '', + height, + isCopyEnabled = false, + isDarkTheme = false, + isDownloadEnabled = false, + isFullHeight = false, + isHeaderPlain = false, + isLanguageLabelVisible = false, + isLineNumbersVisible = true, + isMinimapVisible = false, + isReadOnly = false, + isUploadEnabled = false, + language = Language.plaintext, + loading = '', + onChange = () => {}, + onCodeChange = () => {}, + onDownload = defaultOnDownload, + onEditorDidMount = () => {}, + options = {}, + overrideServices = {}, + shortcutsPopoverButtonText = 'View Shortcuts', + shortcutsPopoverProps = { bodyContent: '', 'aria-label': 'Keyboard Shortcuts' }, + showEditor = true, + toolTipCopyExitDelay = 1600, + toolTipDelay = 300, + toolTipMaxWidth = '100px', + toolTipPosition = 'top', + uploadButtonAriaLabel = 'Upload code', + uploadButtonToolTipText = 'Upload', + width = '' +}: CodeEditorProps) => { + const [value, setValue] = useState(code); + const [isLoading, setIsLoading] = useState(false); + const [showEmptyState, setShowEmptyState] = useState(true); + const [copied, setCopied] = useState(false); - constructor(props: CodeEditorProps) { - super(props); - this.state = { - value: this.props.code, - filename: '', - isLoading: false, - showEmptyState: true, - copied: false - }; - } + const editorRef = useRef(null); + const wrapperRef = useRef(null); + const ref = useRef(null); + const observer = useRef(() => {}); + + const setHeightToFitContent = () => { + const contentHeight = editorRef.current?.getContentHeight(); + const layoutInfo = editorRef.current?.getLayoutInfo(); + editorRef.current?.layout({ width: layoutInfo.width, height: contentHeight }); + }; - onChange: ChangeHandler = (value, event) => { - if (this.props.onChange) { - this.props.onChange(value, event); + const onModelChange: ChangeHandler = (value, event) => { + if (height === 'sizeToFit') { + setHeightToFitContent(); + } + if (onChange) { + onChange(value, event); } - this.setState({ value }); + setValue(value); + onCodeChange(value); }; - handleResize = () => { - if (this.editor) { - this.editor.layout(); + const handleResize = () => { + if (editorRef.current) { + editorRef.current.layout({ width: 0, height: 0 }); // ensures the editor won't take up more space than it needs + editorRef.current.layout(); } }; - componentDidUpdate(prevProps: CodeEditorProps) { - const { code } = this.props; - if (prevProps.code !== code) { - this.setState({ value: code }); + const handleGlobalKeys = (event: KeyboardEvent) => { + if (wrapperRef.current === document.activeElement && (event.key === 'ArrowDown' || event.key === ' ')) { + editorRef.current?.focus(); + event.preventDefault(); } - } + }; - componentDidMount() { - document.addEventListener('keydown', this.handleGlobalKeys); - this.observer = getResizeObserver(this.ref.current, this.handleResize); - this.handleResize(); - } + // if the code changes due to the prop changing + // set the value to the code prop + useEffect(() => setValue(code), [code]); - componentWillUnmount() { - document.removeEventListener('keydown', this.handleGlobalKeys); - this.observer(); - } + useEffect(() => { + document.addEventListener('keydown', handleGlobalKeys); + observer.current = getResizeObserver(ref.current, handleResize, true); + handleResize(); + return () => { + document.removeEventListener('keydown', handleGlobalKeys); + observer.current(); + }; + }, []); - handleGlobalKeys = (event: KeyboardEvent) => { - if (this.wrapperRef.current === document.activeElement && (event.key === 'ArrowDown' || event.key === ' ')) { - this.editor?.focus(); - event.preventDefault(); - } + const editorBeforeMount: BeforeMount = (monaco) => { + defineThemes(monaco.editor); + editorProps?.beforeMount?.(monaco); }; - editorDidMount: EditorDidMount = (editor, monaco) => { + const editorDidMount: EditorDidMount = (editor, monaco) => { // eslint-disable-next-line no-bitwise - editor.addCommand(monaco.KeyMod.Shift | monaco.KeyCode.Tab, () => this.wrapperRef.current.focus()); - Array.from(document.getElementsByClassName('monaco-editor')).forEach(editorElement => + editor.addCommand(monaco.KeyMod.Shift | monaco.KeyCode.Tab, () => wrapperRef.current.focus()); + Array.from(document.getElementsByClassName('monaco-editor')).forEach((editorElement) => editorElement.removeAttribute('role') ); - this.props.onEditorDidMount(editor, monaco); - this.editor = editor; + onEditorDidMount(editor, monaco); + editorRef.current = editor; + if (height === 'sizeToFit') { + setHeightToFitContent(); + } }; - handleFileChange = (value: string, filename: string) => { - this.setState({ - value, - filename - }); + const handleFileChange = (value: string) => { + setValue(value); + onCodeChange(value); }; - handleFileReadStarted = () => this.setState({ isLoading: true }); - handleFileReadFinished = () => this.setState({ isLoading: false }); + const handleFileReadStarted = () => setIsLoading(true); + const handleFileReadFinished = () => setIsLoading(false); - readFile(fileHandle: Blob) { - return new Promise((resolve, reject) => { + const readFile = (fileHandle: Blob) => + new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result as string); reader.onerror = () => reject(reader.error); reader.readAsText(fileHandle); }); - } - onDropAccepted = (acceptedFiles: File[]) => { + const onDropAccepted = (acceptedFiles: File[]) => { if (acceptedFiles.length > 0) { const fileHandle = acceptedFiles[0]; - this.handleFileChange('', fileHandle.name); // Show the filename while reading - this.handleFileReadStarted(); - this.readFile(fileHandle) - .then(data => { - this.handleFileReadFinished(); - this.handleFileChange(data, fileHandle.name); + handleFileChange(''); // Show the filename while reading + handleFileReadStarted(); + readFile(fileHandle) + .then((data) => { + handleFileReadFinished(); + setShowEmptyState(false); + handleFileChange(data); }) .catch((error: DOMException) => { // eslint-disable-next-line no-console console.error('error', error); - this.handleFileReadFinished(); - this.handleFileChange('', ''); // Clear the filename field on a failure + handleFileReadFinished(); + handleFileChange(''); }); } }; - onDropRejected = (rejectedFiles: File[]) => { + const onDropRejected = (rejectedFiles: FileRejection[]) => { if (rejectedFiles.length > 0) { // eslint-disable-next-line no-console console.error('There was an error accepting that dropped file'); // TODO } }; - copyCode = () => { - if (this.timer) { - window.clearTimeout(this.timer); - this.setState({ copied: false }); - } - this.editor?.focus(); - document.execCommand('copy'); - this.setState({ copied: true }, () => { - this.timer = window.setTimeout(() => { - this.setState({ copied: false }); - this.timer = null; - }, 2500); - }); + const copyCode = () => { + navigator.clipboard.writeText(value); + setCopied(true); }; - download = () => { - const { value } = this.state; - const element = document.createElement('a'); - const file = new Blob([value], { type: 'text' }); - element.href = URL.createObjectURL(file); - element.download = `${this.props.downloadFileName}.${CodeEditor.getExtensionFromLanguage(this.props.language)}`; - document.body.appendChild(element); // Required for this to work in FireFox - element.click(); + const editorOptions: editor.IStandaloneEditorConstructionOptions = { + fontFamily: monoFont.var, + scrollBeyondLastLine: height !== 'sizeToFit', + readOnly: isReadOnly, + cursorStyle: 'line', + lineNumbers: isLineNumbersVisible ? 'on' : 'off', + tabIndex: -1, + minimap: { + enabled: isMinimapVisible + }, + ...options }; - toggleEmptyState = () => { - this.setState({ showEmptyState: false }); + const tooltipProps = { + position: toolTipPosition, + exitDelay: toolTipDelay, + entryDelay: toolTipDelay, + maxWidth: toolTipMaxWidth, + trigger: 'mouseenter focus' }; - render() { - const { value, isLoading, showEmptyState, copied } = this.state; - const { - isDarkTheme, - height, - width, - className, - isCopyEnabled, - copyButtonSuccessTooltipText, - isReadOnly, - isUploadEnabled, - isLanguageLabelVisible, - copyButtonAriaLabel, - copyButtonToolTipText, - uploadButtonAriaLabel, - uploadButtonToolTipText, - downloadButtonAriaLabel, - downloadButtonToolTipText, - toolTipDelay, - toolTipCopyExitDelay, - toolTipMaxWidth, - toolTipPosition, - isLineNumbersVisible, - isDownloadEnabled, - language, - emptyState: providedEmptyState, - emptyStateTitle, - emptyStateBody, - emptyStateButton, - emptyStateLink, - customControls, - isMinimapVisible, - showEditor, - options: optionsProp, - overrideServices - } = this.props; - const options: editor.IStandaloneEditorConstructionOptions = { - readOnly: isReadOnly, - cursorStyle: 'line', - lineNumbers: isLineNumbersVisible ? 'on' : 'off', - tabIndex: -1, - minimap: { - enabled: isMinimapVisible - }, - ...optionsProp - }; + const hasEditorHeaderContent = + ((isCopyEnabled || isDownloadEnabled) && (!showEmptyState || !!value)) || + isUploadEnabled || + customControls || + headerMainContent || + !!shortcutsPopoverProps.bodyContent; - return ( - - {({ getRootProps, getInputProps, isDragActive, open }) => { - const emptyState = - providedEmptyState || - (isUploadEnabled ? ( - - - - {emptyStateTitle} - - {emptyStateBody} - - - - - - ) : ( - - - - {emptyStateTitle} - - - - )); - - const editorHeader = ( -
    - {(isCopyEnabled || isDownloadEnabled || isUploadEnabled || customControls) && ( -
    - {isCopyEnabled && (!showEmptyState || !!value) && ( - {copied ? copyButtonSuccessTooltipText : copyButtonToolTipText}
    } - exitDelay={copied ? toolTipCopyExitDelay : toolTipDelay} - entryDelay={toolTipDelay} - maxWidth={toolTipMaxWidth} - position={toolTipPosition} - > - - - )} - {isUploadEnabled && ( - {uploadButtonToolTipText}
    } - entryDelay={toolTipDelay} - exitDelay={toolTipDelay} - maxWidth={toolTipMaxWidth} - position={toolTipPosition} - > - - - )} - {isDownloadEnabled && (!showEmptyState || !!value) && ( - {downloadButtonToolTipText}
    } - entryDelay={toolTipDelay} - exitDelay={toolTipDelay} - maxWidth={toolTipMaxWidth} - position={toolTipPosition} - > - - - )} - {customControls && ( - {customControls} - )} -
    + return ( + + {({ getRootProps, getInputProps, isDragActive, open }) => { + const hiddenFileInput = ; + + const editorEmptyState = + emptyState || + (isUploadEnabled ? ( + + {emptyStateBody} + {!isReadOnly && ( + + + + + + + + )} - {isLanguageLabelVisible && ( -
    - - - - {language.toUpperCase()} -
    +
    + ) : ( + + {!isReadOnly && ( + + + + + )} + + )); + + const editorHeaderContent = ( + <> +
    + + {isCopyEnabled && (!showEmptyState || !!value) && ( + } + aria-label={copyButtonAriaLabel} + tooltipProps={{ + ...tooltipProps, + 'aria-live': 'polite', + content:
    {copied ? copyButtonSuccessTooltipText : copyButtonToolTipText}
    , + exitDelay: copied ? toolTipCopyExitDelay : toolTipDelay, + onTooltipHidden: () => setCopied(false) + }} + onClick={copyCode} + /> + )} + {isUploadEnabled && ( + } + aria-label={uploadButtonAriaLabel} + tooltipProps={{ content:
    {uploadButtonToolTipText}
    , ...tooltipProps }} + onClick={open} + /> + )} + {isDownloadEnabled && (!showEmptyState || !!value) && ( + } + aria-label={downloadButtonAriaLabel} + tooltipProps={{ content:
    {downloadButtonToolTipText}
    , ...tooltipProps }} + onClick={() => { + onDownload(value, `${downloadFileName}.${getExtensionFromLanguage(language)}`); + }} + /> + )} + {customControls && customControls} +
    - ); - - const editor = ( -
    - -
    - ); - - return ( -
    - {isUploadEnabled || providedEmptyState ? ( -
    event.preventDefault() // Prevents clicking TextArea from opening file dialog - })} - className={`pf-c-file-upload ${isDragActive && 'pf-m-drag-hover'} ${isLoading && 'pf-m-loading'}`} - > - {editorHeader} + {headerMainContent &&
    {headerMainContent}
    } + {!!shortcutsPopoverProps.bodyContent && ( +
    + + + +
    + )} + + ); + + const editorHeader = ( +
    + {hasEditorHeaderContent &&
    {editorHeaderContent}
    } + {isLanguageLabelVisible && ( +
    + + + + {language.toUpperCase()} +
    + )} +
    + ); + + const editor = ( +
    + +
    + ); + + return ( +
    + {isUploadEnabled || emptyState ? ( +
    event.stopPropagation() // Prevents clicking TextArea from opening file dialog + })} + className={css(styles.codeEditorContainer, isLoading && fileUploadStyles.modifiers.loading)} + > + {editorHeader} +
    + {(showEmptyState || emptyState) && !value ? ( +
    + {hiddenFileInput} + {editorEmptyState} +
    + ) : ( + <> + {hiddenFileInput} + {editor} + + )} +
    +
    + ) : ( + <> + {editorHeader} + {showEditor && (
    - - {(showEmptyState || providedEmptyState) && !value ? emptyState : editor} + {hiddenFileInput} + {editor}
    -
    - ) : ( - <> - {editorHeader} - {showEditor &&
    {editor}
    } - - )} -
    - ); - }} - - ); - } -} + )} + + )} +
    + ); + }} +
    + ); +}; + +CodeEditor.displayName = 'CodeEditor'; diff --git a/packages/react-code-editor/src/components/CodeEditor/CodeEditorControl.tsx b/packages/react-code-editor/src/components/CodeEditor/CodeEditorControl.tsx index 67b229732e2..aea9def50bf 100644 --- a/packages/react-code-editor/src/components/CodeEditor/CodeEditorControl.tsx +++ b/packages/react-code-editor/src/components/CodeEditor/CodeEditorControl.tsx @@ -1,61 +1,52 @@ -import * as React from 'react'; -import { Button, ButtonProps, PopoverPosition, Tooltip } from '@patternfly/react-core'; +import { useContext } from 'react'; +import { Button, ButtonProps } from '@patternfly/react-core/dist/esm/components/Button'; +import { Tooltip } from '@patternfly/react-core/dist/esm/components/Tooltip'; import { CodeEditorContext } from './CodeEditorUtils'; +/** Allows customizing the code editor controls by passing this sub-component into the + * code editor's customControl property. + */ + export interface CodeEditorControlProps extends Omit { - /** icon rendered inside the code editor control */ - icon: React.ReactNode; - /** additional classes added to the Code editor control */ - className?: string; - /** accessible label for the code editor control */ + /** Accessible label for the code editor control */ 'aria-label'?: string; - /** Text to display in the tooltip*/ - toolTipText: React.ReactNode; - /** Copy button popover position. */ - position?: PopoverPosition | 'auto' | 'top' | 'bottom' | 'left' | 'right'; - /** Maximum width of the tooltip (default 150px). */ - maxWidth?: string; - /** Delay in ms before the tooltip disappears. */ - exitDelay?: number; - /** Delay in ms before the tooltip appears. */ - entryDelay?: number; + /** Additional classes added to the code editor control. */ + className?: string; + /** Icon rendered inside the code editor control. */ + icon?: React.ReactNode; /** Event handler for the click of the button */ onClick: (code: string, event?: any) => void; - /** Flag indicating that the button is visible above the code editor */ + /** Flag indicating that the button is visible above the code editor. */ isVisible?: boolean; + /** Additional tooltip props forwarded to the Tooltip component */ + tooltipProps?: any; } export const CodeEditorControl: React.FunctionComponent = ({ icon, className, 'aria-label': ariaLabel, - toolTipText, - exitDelay = 0, - entryDelay = 300, - maxWidth = '100px', - position = 'top', onClick = () => {}, isVisible = true, + tooltipProps = {}, ...props }: CodeEditorControlProps) => { - const context = React.useContext(CodeEditorContext); + const context = useContext(CodeEditorContext); const onCustomClick = (event: React.MouseEvent) => { onClick(context.code, event); }; return isVisible ? ( - {toolTipText}} - > - + + + +
    + +
    +
    + +
    + + + +
    + +
    +
    +
    +
    +
    + + `; -exports[`CodeEditor with all flags 1`] = ` - - - +exports[`Matches snapshot without props 1`] = ` + +
    +
    +
    + +
    +
    +
    +
    +
    + `; diff --git a/packages/react-code-editor/src/components/CodeEditor/__test__/__snapshots__/CodeEditorControl.test.tsx.snap b/packages/react-code-editor/src/components/CodeEditor/__test__/__snapshots__/CodeEditorControl.test.tsx.snap new file mode 100644 index 00000000000..5751d125bc9 --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/__test__/__snapshots__/CodeEditorControl.test.tsx.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches snapshot 1`] = ` + +
    + +
    +
    +`; diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditor.md b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditor.md index 25ff65cf02a..d08e97eb061 100644 --- a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditor.md +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditor.md @@ -1,179 +1,63 @@ --- id: Code editor section: components -cssPrefix: pf-c-code-editor -propComponents: ['CodeEditor'] -beta: true +cssPrefix: pf-v6-c-code-editor +propComponents: ['CodeEditor', 'CodeEditorControl', 'Popover'] --- Note: Code editor lives in its own package at [@patternfly/react-code-editor](https://www.npmjs.com/package/@patternfly/react-code-editor) and has [**required peer deps**](https://github.com/patternfly/patternfly-react/blob/main/packages/react-code-editor/package.json). +import { Fragment, useState } from 'react'; import { CodeEditor, CodeEditorControl, Language } from '@patternfly/react-code-editor'; +import RhUiSettingsFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-settings-fill-icon'; +import HashtagIcon from '@patternfly/react-icons/dist/esm/icons/hashtag-icon'; +import MapIcon from '@patternfly/react-icons/dist/esm/icons/map-icon'; +import MoonIcon from '@patternfly/react-icons/dist/esm/icons/moon-icon'; import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; +import FontIcon from '@patternfly/react-icons/dist/esm/icons/font-icon'; ## Examples + ### Basic -```js -import React from 'react'; -import { CodeEditor, Language } from '@patternfly/react-code-editor'; -import { Checkbox } from '@patternfly/react-core'; - -class BasicCodeEditor extends React.Component { - constructor(props) { - super(props); - this.state = { - isDarkTheme: false, - isLineNumbersVisible: true, - isReadOnly: false, - isMinimapVisible: true - }; - - this.toggleDarkTheme = checked => { - this.setState({ - isDarkTheme: checked - }); - }; - this.toggleLineNumbers = checked => { - this.setState({ - isLineNumbersVisible: checked - }); - }; - this.toggleReadOnly = checked => { - this.setState({ - isReadOnly: checked - }); - }; - this.toggleMinimap = checked => { - this.setState({ - isMinimapVisible: checked - }) - }; - - this.onEditorDidMount = (editor, monaco) => { - console.log(editor.getValue()); - editor.layout(); - editor.focus(); - monaco.editor.getModels()[0].updateOptions({ tabSize: 5 }); - }; - - this.onChange = value => { - console.log(value); - }; - } - - render() { - const { isDarkTheme, isLineNumbersVisible, isReadOnly, isMinimapVisible } = this.state; - - return ( - <> - - - - - - - ); - } -} + +```ts file="./CodeEditorBasic.tsx" + +``` + +### With sizeToFit height, height will grow/shrink with content + +```ts file="./CodeEditorSizeToFit.tsx" + +``` + +### With isFullHeight height, height will match the size of the parent + +```ts file="CodeEditorFullHeight.tsx" + +``` + +### With shortcut menu and main header content + +These examples below are the shortcuts that we recommend describing in the popover since they are monaco features. + +```ts file="./CodeEditorShortcutMainHeader.tsx" + ``` ### With actions -```js -import React from 'react'; -import { CodeEditor } from '@patternfly/react-code-editor'; - - + +```ts file="./CodeEditorWithActions.tsx" + ``` ### With custom control -```js -import React from 'react'; -import { CodeEditor, CodeEditorControl } from '@patternfly/react-code-editor'; -import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; -class customControlExample extends React.Component { - constructor(props) { - super(props); - this.state = { - code: '' - }; - - this.onChange = code => { - this.setState({ code }) - }; - - this.onExecuteCode = (code) => { - console.log(code); - }; - } - - render() { - const customControl = ( - } - aria-label="Execute code" - toolTipText="Execute code" - onClick={this.onExecuteCode} - isVisible={this.state.code !== ''} - />); - - return ( - <> - - - ); - } -} +```ts file="CodeEditorCustomControl.tsx" + +``` + +### With configuration modal + +```ts file="CodeEditorConfigurationModal.tsx" + ``` diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorBasic.tsx b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorBasic.tsx new file mode 100644 index 00000000000..b31bc694360 --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorBasic.tsx @@ -0,0 +1,84 @@ +import { useState } from 'react'; +import { CodeEditor, Language } from '@patternfly/react-code-editor'; +import { Checkbox } from '@patternfly/react-core'; + +export const CodeEditorBasic: React.FunctionComponent = () => { + const [isDarkTheme, setIsDarkTheme] = useState(false); + const [isLineNumbersVisible, setIsLineNumbersVisible] = useState(true); + const [isReadOnly, setIsReadOnly] = useState(false); + const [isMinimapVisible, setIsMinimapVisible] = useState(false); + + const toggleDarkTheme = (checked) => { + setIsDarkTheme(checked); + }; + + const toggleLineNumbers = (checked) => { + setIsLineNumbersVisible(checked); + }; + const toggleReadOnly = (checked) => { + setIsReadOnly(checked); + }; + const toggleMinimap = (checked) => { + setIsMinimapVisible(checked); + }; + + const onEditorDidMount = (editor, monaco) => { + editor.layout(); + editor.focus(); + monaco.editor.getModels()[0].updateOptions({ tabSize: 5 }); + }; + + const onChange = (value) => { + // eslint-disable-next-line no-console + console.log(value); + }; + + return ( + <> + toggleDarkTheme(checked)} + aria-label="dark theme checkbox" + id="toggle-theme" + name="toggle-theme" + /> + toggleLineNumbers(checked)} + aria-label="line numbers checkbox" + id="toggle-line-numbers" + name="toggle-line-numbers" + /> + toggleReadOnly(checked)} + aria-label="read only checkbox" + id="toggle-read-only" + name="toggle-read-only" + /> + toggleMinimap(checked)} + aria-label="display minimap checkbox" + id="toggle-minimap" + name="toggle-minimap" + /> + + + ); +}; diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorConfigurationModal.tsx b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorConfigurationModal.tsx new file mode 100644 index 00000000000..85fc7fe4fd9 --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorConfigurationModal.tsx @@ -0,0 +1,230 @@ +import RhUiSettingsFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-settings-fill-icon'; +import MapIcon from '@patternfly/react-icons/dist/esm/icons/map-icon'; +import MoonIcon from '@patternfly/react-icons/dist/esm/icons/moon-icon'; +import HashtagIcon from '@patternfly/react-icons/dist/esm/icons/hashtag-icon'; +import FontIcon from '@patternfly/react-icons/dist/esm/icons/font-icon'; +import { CodeEditor, CodeEditorControl } from '@patternfly/react-code-editor'; +import { + Flex, + FlexItem, + Icon, + Modal, + ModalBody, + ModalHeader, + NumberInput, + Switch, + SwitchProps +} from '@patternfly/react-core'; +import { useState } from 'react'; + +interface ConfigModalItemProps { + /** Icon rendered inside the configuration modal. */ + icon?: React.ReactNode; + /** Description of the configuration option. */ + description: string; + /** Title of the configuration option. We assume that titles are unique. */ + title: string; + /** + * Optional ID of the configuration option. Also used as a prefix for the following elements: + * - `${id}-title` for the element which contains the title + * - `${id}-description` for the element which contains the description + */ + id?: string; + /** + * Slot to render inside the configuration modal. Remember to add `aria-labelledby` and `aria-describedby` props + * to the control inside the slot, pointing to the title and description ids respectively. + */ + slot?: React.ReactNode; +} + +const ConfigModalItem: React.FunctionComponent = ({ + icon = , + description, + title, + id = `ConfigModalItem-${title.replace(/\s+/g, '-').toLowerCase()}`, + slot +}) => ( + + + + {icon} + + {title} + + + +
    {description}
    +
    + {slot} +
    +); + +interface ConfigModalSwitchProps extends Omit { + /** Flag indicating whether the option is enabled or disabled. */ + isChecked?: SwitchProps['isChecked']; + /** onChange handler for the switch. */ + onChange?: SwitchProps['onChange']; + /** Labels for the enabled and disabled states of the switch. */ + labels?: { + enabled: string; + disabled: string; + }; +} + +const ConfigModalSwitch: React.FunctionComponent = ({ + icon = , + description, + title, + id = `ConfigModalSwitch-${title.replace(/\s+/g, '-').toLowerCase()}`, + isChecked = false, + onChange, + labels = { enabled: undefined, disabled: undefined } +}) => ( + + } + /> +); + +interface ConfigModalControlProps { + /** Controls to be rendered inside the configuration modal. */ + children: React.ReactNode; + /** Title of the configuration modal. */ + title?: string; + /** Description of the configuration modal. */ + description?: string; + /** Optional ID of the configuration modal. Also used as a prefix for the ids of inner elements and the OUIA id. */ + ouiaId?: string; +} + +const ConfigModalControl: React.FunctionComponent = ({ + children, + title = 'Editor settings', + description = 'Changes apply immediately', + ouiaId = 'CodeEditorConfigurationModal' +}: ConfigModalControlProps) => { + const [isModalOpen, setIsModalOpen] = useState(false); + + return ( + <> + setIsModalOpen(false)} + ouiaId={ouiaId} + variant="small" + > + + + + {children} + + + + setIsModalOpen(true)} + tooltipProps={{ content: title, ariaLive: 'off' }} + /> + + ); +}; + +export const CodeEditorConfigurationModal: React.FunctionComponent = () => { + const [code, setCode] = useState('Some example content'); + + const [isMinimapVisible, setIsMinimapVisible] = useState(true); + const [isDarkTheme, setIsDarkTheme] = useState(false); + const [isLineNumbersVisible, setIsLineNumbersVisible] = useState(true); + const [fontSize, setFontSize] = useState(14); + + const onChange = (code: string) => { + setCode(code); + }; + + const customControl = ( + + setIsMinimapVisible(checked)} + icon={} + /> + setIsDarkTheme(checked)} + icon={} + /> + setIsLineNumbersVisible(checked)} + icon={} + /> + } + slot={ + setFontSize((size) => Math.max(5, size - 1))} + onChange={(event) => setFontSize(Number((event.target as HTMLInputElement).value))} + onPlus={() => setFontSize((size) => size + 1)} + widthChars={2} + /> + } + /> + + ); + + return ( + + ); +}; diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorCustomControl.tsx b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorCustomControl.tsx new file mode 100644 index 00000000000..fe470c3f3da --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorCustomControl.tsx @@ -0,0 +1,38 @@ +import { useState } from 'react'; +import { CodeEditor, CodeEditorControl } from '@patternfly/react-code-editor'; +import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; + +export const CodeEditorCustomControl: React.FunctionComponent = () => { + const [code, setCode] = useState('Some example content'); + + const onChange = (code) => { + setCode(code); + }; + + const onExecuteCode = (code) => { + // eslint-disable-next-line no-console + console.log(code); + }; + + const customControl = ( + } + aria-label="Execute code" + tooltipProps={{ content: 'Execute code' }} + onClick={onExecuteCode} + isVisible={code !== ''} + /> + ); + + return ( + + ); +}; diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorFullHeight.tsx b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorFullHeight.tsx new file mode 100644 index 00000000000..760fa00ea84 --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorFullHeight.tsx @@ -0,0 +1,26 @@ +import { CodeEditor, Language } from '@patternfly/react-code-editor'; + +export const CodeEditorFullHeight: React.FunctionComponent = () => { + const onEditorDidMount = (editor, monaco) => { + editor.layout(); + editor.focus(); + monaco.editor.getModels()[0].updateOptions({ tabSize: 5 }); + }; + + const onChange = (value) => { + // eslint-disable-next-line no-console + console.log(value); + }; + + return ( +
    + +
    + ); +}; diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorShortcutMainHeader.tsx b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorShortcutMainHeader.tsx new file mode 100644 index 00000000000..8efd31d562c --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorShortcutMainHeader.tsx @@ -0,0 +1,104 @@ +import { Fragment, useState } from 'react'; +import { CodeEditor, Language } from '@patternfly/react-code-editor'; +import { Grid, GridItem, Label, Radio } from '@patternfly/react-core'; + +export const CodeEditorShortcutMainHeader: React.FunctionComponent = () => { + type ShortcutMode = 'PC' | 'Mac'; + + const [currentShortcutMode, setCurrentShortcutMode] = useState('PC'); + + const onEditorDidMount = (editor, monaco) => { + editor.layout(); + editor.focus(); + monaco.editor.getModels()[0].updateOptions({ tabSize: 5 }); + }; + + const onChange = (value: string) => { + // eslint-disable-next-line no-console + console.log(value); + }; + + const onShortcutModeChange = (event: React.FormEvent, checked: boolean) => { + if (checked) { + const newMode = event.currentTarget.value as ShortcutMode; + setCurrentShortcutMode(newMode); + } + }; + + const shortcuts = [ + { + PC: ['Alt', 'F1'], + Mac: ['Opt', 'F1'], + description: 'Accessibility helps' + }, + { + PC: ['F1'], + Mac: ['F1'], + description: 'View all editor shortcuts' + }, + { + PC: ['Ctrl', 'Space'], + Mac: ['Opt', 'Esc'], + description: 'Activate auto complete' + }, + { + PC: ['Ctrl', 'S'], + Mac: ['Cmd', 'S'], + description: 'Save' + } + ]; + const shortcutsPopoverProps = { + bodyContent: ( + + {shortcuts.map((shortcut, index) => ( + + + {shortcut[currentShortcutMode] + .map((key) => ( + + )) + .reduce((prev, curr) => ( + <>{[prev, ' + ', curr]} + ))} + + {shortcut.description} + + ))} + + ), + 'aria-label': 'Shortcuts' + }; + + return ( + <> + + + + + ); +}; diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorSizeToFit.tsx b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorSizeToFit.tsx new file mode 100644 index 00000000000..cc1ba11ccd7 --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorSizeToFit.tsx @@ -0,0 +1,24 @@ +import { CodeEditor, Language } from '@patternfly/react-code-editor'; + +export const CodeEditorSizeToFit: React.FunctionComponent = () => { + const onEditorDidMount = (editor, monaco) => { + editor.layout(); + editor.focus(); + monaco.editor.getModels()[0].updateOptions({ tabSize: 5 }); + }; + + const onChange = (value) => { + // eslint-disable-next-line no-console + console.log(value); + }; + + return ( + + ); +}; diff --git a/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorWithActions.tsx b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorWithActions.tsx new file mode 100644 index 00000000000..3b530303cde --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/examples/CodeEditorWithActions.tsx @@ -0,0 +1,5 @@ +import { CodeEditor } from '@patternfly/react-code-editor'; + +export const CodeEditorWithActions: React.FunctionComponent = () => ( + +); diff --git a/packages/react-code-editor/src/components/CodeEditor/themeTokenMapping.ts b/packages/react-code-editor/src/components/CodeEditor/themeTokenMapping.ts new file mode 100644 index 00000000000..35ad86bf8b0 --- /dev/null +++ b/packages/react-code-editor/src/components/CodeEditor/themeTokenMapping.ts @@ -0,0 +1,83 @@ +import backgroundDark from '@patternfly/react-tokens/dist/esm/t_color_gray_90'; +import textColorDark from '@patternfly/react-tokens/dist/esm/t_color_white'; +import textColorSubtleDark from '@patternfly/react-tokens/dist/esm/t_color_gray_30'; + +import redDark from '@patternfly/react-tokens/dist/esm/t_color_red_30'; +import orangeredDark from '@patternfly/react-tokens/dist/esm/t_color_red_orange_30'; +import orangeDark from '@patternfly/react-tokens/dist/esm/t_color_orange_30'; +import yellowDark from '@patternfly/react-tokens/dist/esm/t_color_yellow_30'; +import greenDark from '@patternfly/react-tokens/dist/esm/t_color_green_30'; +import tealDark from '@patternfly/react-tokens/dist/esm/t_color_teal_30'; +import blueDark from '@patternfly/react-tokens/dist/esm/t_color_blue_30'; +import purpleDark from '@patternfly/react-tokens/dist/esm/t_color_purple_30'; +import grayDark from '@patternfly/react-tokens/dist/esm/t_color_gray_30'; + +import backgroundLight from '@patternfly/react-tokens/dist/esm/t_color_white'; +import textColorLight from '@patternfly/react-tokens/dist/esm/t_global_text_color_100'; +import textColorSubtleLight from '@patternfly/react-tokens/dist/esm/t_global_text_color_200'; + +import redLight from '@patternfly/react-tokens/dist/esm/t_color_red_50'; +import orangeredLight from '@patternfly/react-tokens/dist/esm/t_color_red_orange_50'; +import orangeLight from '@patternfly/react-tokens/dist/esm/t_color_orange_50'; +import yellowLight from '@patternfly/react-tokens/dist/esm/t_color_yellow_50'; +import greenLight from '@patternfly/react-tokens/dist/esm/t_color_green_50'; +import tealLight from '@patternfly/react-tokens/dist/esm/t_color_teal_50'; +import blueLight from '@patternfly/react-tokens/dist/esm/t_color_blue_50'; +import purpleLight from '@patternfly/react-tokens/dist/esm/t_color_purple_50'; +import grayLight from '@patternfly/react-tokens/dist/esm/t_color_gray_50'; + +/** + * This file maps the theme tokens from PatternFly to a format that can be used in the Monaco editor. + * + * @see https://github.com/microsoft/monaco-editor/issues/2427 + */ +export const colors = { + background: { + dark: backgroundDark.value, + light: backgroundLight.value + }, + foreground: { + dark: textColorDark.value, + light: textColorLight.value + }, + secondaryForeground: { + dark: textColorSubtleDark.value, + light: textColorSubtleLight.value + }, + red: { + dark: redDark.value, + light: redLight.value + }, + orangered: { + dark: orangeredLight.value, + light: orangeredDark.value + }, + orange: { + dark: orangeDark.value, + light: orangeLight.value + }, + yellow: { + dark: yellowDark.value, + light: yellowLight.value + }, + green: { + dark: greenDark.value, + light: greenLight.value + }, + teal: { + dark: tealDark.value, + light: tealLight.value + }, + blue: { + dark: blueDark.value, + light: blueLight.value + }, + purple: { + dark: purpleDark.value, + light: purpleLight.value + }, + gray: { + dark: grayDark.value, + light: grayLight.value + } +}; diff --git a/packages/react-console/.npmignore b/packages/react-console/.npmignore deleted file mode 100644 index b1655e5e919..00000000000 --- a/packages/react-console/.npmignore +++ /dev/null @@ -1 +0,0 @@ -dist/*.tsbuildinfo \ No newline at end of file diff --git a/packages/react-console/CHANGELOG.md b/packages/react-console/CHANGELOG.md deleted file mode 100644 index b2aa02721dd..00000000000 --- a/packages/react-console/CHANGELOG.md +++ /dev/null @@ -1,3214 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# 4.39.0 (2022-01-14) - - -### Features - -* **DescriptionList:** add option to fill columns first ([#6736](https://github.com/patternfly/patternfly-react/issues/6736)) ([c955c29](https://github.com/patternfly/patternfly-react/commit/c955c2917dbc4b85ce58fac4f93845c429186e1b)) - - - - - -## 4.38.2 (2022-01-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.38.1 (2022-01-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.38.0 (2022-01-12) - - -### Features - -* **expandable-section:** added indented variation ([#6763](https://github.com/patternfly/patternfly-react/issues/6763)) ([703b922](https://github.com/patternfly/patternfly-react/commit/703b9224e43bedd5b37ec41d8f26f2939836d610)) - - - - - -## 4.37.1 (2022-01-11) - - -### Bug Fixes - -* **Select:** update typeahead Select children when any option attribute changes ([#6747](https://github.com/patternfly/patternfly-react/issues/6747)) ([1e03f3c](https://github.com/patternfly/patternfly-react/commit/1e03f3c6d0a7c507e33398c98863e40bb2233a62)) - - - - - -# 4.37.0 (2022-01-11) - - -### Features - -* **ToggleGroup:** support disabling all items under the parent ([#6700](https://github.com/patternfly/patternfly-react/issues/6700)) ([a60c8f3](https://github.com/patternfly/patternfly-react/commit/a60c8f3485546c797750451714a70b7e84a4ba0f)) - - - - - -## 4.36.1 (2022-01-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.36.0 (2022-01-11) - - -### Features - -* **Table:** update clickable area for checks/radios ([#6754](https://github.com/patternfly/patternfly-react/issues/6754)) ([c4f3c2d](https://github.com/patternfly/patternfly-react/commit/c4f3c2d7f515e3d6ad73d8b52238ca426281469a)) - - - - - -## 4.35.2 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.35.1 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.35.0 (2022-01-10) - - -### Features - -* **Dropdown:** add plain-text variant support ([#6721](https://github.com/patternfly/patternfly-react/issues/6721)) ([e5000e3](https://github.com/patternfly/patternfly-react/commit/e5000e36194e36b9c6ae49efdb0a513125efcb70)) - - - - - -## 4.34.11 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.34.10 (2022-01-10) - - -### Bug Fixes - -* **Tabs:** allow href navigation from tabs ([#6755](https://github.com/patternfly/patternfly-react/issues/6755)) ([290d89a](https://github.com/patternfly/patternfly-react/commit/290d89aed2dd4517db9859cc80ef2745cb8a779b)) - - - - - -## 4.34.9 (2022-01-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.34.8 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.34.7 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.34.6 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.34.5 (2022-01-07) - - -### Bug Fixes - -* **jumplinks:** Updated JumpLinks demo to allow for horizontal display ([#6731](https://github.com/patternfly/patternfly-react/issues/6731)) ([f37b934](https://github.com/patternfly/patternfly-react/commit/f37b9342e678da247056c73767d5d40ff5435bda)) - - - - - -## 4.34.4 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.34.3 (2022-01-06) - - -### Bug Fixes - -* **TopologyControlBar:** Update screen reader className to latest ([#6739](https://github.com/patternfly/patternfly-react/issues/6739)) ([ed9da57](https://github.com/patternfly/patternfly-react/commit/ed9da575fddf9fe7af8a891972f7a66520785411)) - - - - - -## 4.34.2 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.34.1 (2022-01-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.34.0 (2022-01-05) - - -### Features - -* **Table:** allow a generic to be passed for cell props ([#6691](https://github.com/patternfly/patternfly-react/issues/6691)) ([e22c7be](https://github.com/patternfly/patternfly-react/commit/e22c7bebf630b7cd71e4dc434c593b69fa2fb2c8)) - - - - - -## 4.33.3 (2022-01-04) - - -### Bug Fixes - -* **docs:** fix broken theme-patternfly-org link ([#6726](https://github.com/patternfly/patternfly-react/issues/6726)) ([4ba15e9](https://github.com/patternfly/patternfly-react/commit/4ba15e9d9611afbb80d995e4d63f5478c4212a9e)) - - - - - -## 4.33.2 (2022-01-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.33.1 (2022-01-04) - - -### Bug Fixes - -* **OverflowMenu:** pass HTMLDivElements props to group and control divs ([#6674](https://github.com/patternfly/patternfly-react/issues/6674)) ([e6d0d64](https://github.com/patternfly/patternfly-react/commit/e6d0d6406a07de04f4b232ca9a21247c0e9746c0)) - - - - - -# 4.33.0 (2021-12-22) - - -### Features - -* **Toolbar:** support customizing text in ToolbarChipGroupContent ([#6694](https://github.com/patternfly/patternfly-react/issues/6694)) ([24266ad](https://github.com/patternfly/patternfly-react/commit/24266adf569c027574abd1503b5e46974220349a)) - - - - - -## 4.32.5 (2021-12-16) - - -### Bug Fixes - -* **LogViewer:** fix the issue that scrollbar could compress the content of the logs ([#6702](https://github.com/patternfly/patternfly-react/issues/6702)) ([11aab1f](https://github.com/patternfly/patternfly-react/commit/11aab1f71a1aa9959cf14b887ab55b845a794a00)) - - - - - -## 4.32.4 (2021-12-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.32.3 (2021-12-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.32.2 (2021-12-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.32.1 (2021-12-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.32.0 (2021-12-09) - - -### Features - -* **Popover:** add composable header and alert variants ([#6664](https://github.com/patternfly/patternfly-react/issues/6664)) ([9028e8b](https://github.com/patternfly/patternfly-react/commit/9028e8ba5d674bde6a7e29532f7926e200dd632a)) - - - - - -## 4.31.1 (2021-12-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.31.0 (2021-12-08) - - -### Features - -* **DualListSelector:** add composable tree example ([#6652](https://github.com/patternfly/patternfly-react/issues/6652)) ([5fe977b](https://github.com/patternfly/patternfly-react/commit/5fe977becb5dea615724abf846f315e50931c188)) - - - - - -## 4.30.1 (2021-12-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.30.0 (2021-12-06) - - -### Features - -* **Card:** Add disabled card and clean up props ([#6659](https://github.com/patternfly/patternfly-react/issues/6659)) ([86f225a](https://github.com/patternfly/patternfly-react/commit/86f225ab2e02d617e2d380c4a7f7593037c50e84)) - - - - - -# 4.29.0 (2021-12-06) - - -### Features - -* **MenuToggle:** add plain with text variant ([#6627](https://github.com/patternfly/patternfly-react/issues/6627)) ([1f4ca5e](https://github.com/patternfly/patternfly-react/commit/1f4ca5e36d7077da3ff3e6918874048c784216e0)) - - - - - -# 4.28.0 (2021-12-06) - - -### Features - -* **Dropdown:** add toggle variants ([#6651](https://github.com/patternfly/patternfly-react/issues/6651)) ([6414309](https://github.com/patternfly/patternfly-react/commit/64143094aec86aed86adb320e059d987af4f5f24)) - - - - - -## 4.27.1 (2021-12-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.27.0 (2021-12-03) - - -### Features - -* **Select:** add ability to persist filtered children state ([#6670](https://github.com/patternfly/patternfly-react/issues/6670)) ([f618577](https://github.com/patternfly/patternfly-react/commit/f618577582e389409978bd1d6512ca0cf5d855cf)) - - - - - -## 4.26.17 (2021-12-03) - - -### Bug Fixes - -* **Slider:** fixed examples with custom steps and input ([#6662](https://github.com/patternfly/patternfly-react/issues/6662)) ([b4cab38](https://github.com/patternfly/patternfly-react/commit/b4cab38a2492564bf91e3711ce322951bcc6a051)) - - - - - -## 4.26.16 (2021-12-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.15 (2021-12-02) - - -### Bug Fixes - -* **Tile:** fix selecting tile in tile demo ([#6653](https://github.com/patternfly/patternfly-react/issues/6653)) ([e12e44d](https://github.com/patternfly/patternfly-react/commit/e12e44d4b623de305b7df04174144a9496d282a7)) - - - - - -## 4.26.14 (2021-12-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.13 (2021-11-30) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.12 (2021-11-30) - - -### Bug Fixes - -* **action-list:** added support for classname ([#6647](https://github.com/patternfly/patternfly-react/issues/6647)) ([dd3d2ce](https://github.com/patternfly/patternfly-react/commit/dd3d2ce32b4d3e7562faf465abdc508e17f097d9)) - - - - - -## 4.26.11 (2021-11-30) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.10 (2021-11-23) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.9 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.8 (2021-11-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.7 (2021-11-18) - - -### Bug Fixes - -* **pagination:** updated toggleTemplate prop description to include ofWord prop ([#6622](https://github.com/patternfly/patternfly-react/issues/6622)) ([26733a6](https://github.com/patternfly/patternfly-react/commit/26733a6a256ad0e873afbc268a712027470fdeaa)) - - - - - -## 4.26.6 (2021-11-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.5 (2021-11-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.4 (2021-11-15) - - -### Bug Fixes - -* **FileUpload:** Downgrade react-dropzone back to 9.0.0 to avoid a breaking type change, fix behavior regressions ([#6610](https://github.com/patternfly/patternfly-react/issues/6610)) ([574bf4f](https://github.com/patternfly/patternfly-react/commit/574bf4ff3ccf7f67ce750bc48067eaf826e99990)) - - - - - -## 4.26.3 (2021-11-15) - - -### Bug Fixes - -* **Menu:** allow maxMenuHeight with Scrollabe ([#6608](https://github.com/patternfly/patternfly-react/issues/6608)) ([8c1f12c](https://github.com/patternfly/patternfly-react/commit/8c1f12c2b0e86bbc5ba1071db3ebf29fee7421a0)) - - - - - -## 4.26.2 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.26.1 (2021-11-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.26.0 (2021-11-12) - - -### Features - -* **card:** added hoverable/selectable/selected-raised variant ([#6565](https://github.com/patternfly/patternfly-react/issues/6565)) ([8c60568](https://github.com/patternfly/patternfly-react/commit/8c60568ba4fa18398fed636710e222ce506de82c)) - - - - - -## 4.25.2 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.25.1 (2021-11-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.25.0 (2021-11-11) - - -### Features - -* **ComposableTable:** add sticky columns and nested headers ([#6538](https://github.com/patternfly/patternfly-react/issues/6538)) ([f11245b](https://github.com/patternfly/patternfly-react/commit/f11245bfccc8c6c02a9d5545a69ed533743cc552)) - - - - - -# 4.24.0 (2021-11-11) - - -### Features - -* **contextselector:** added support for context selector items as links ([#6554](https://github.com/patternfly/patternfly-react/issues/6554)) ([c465388](https://github.com/patternfly/patternfly-react/commit/c4653881eee0cd8ec8e3a7125bbef0bded9f2de0)) - - - - - -# 4.23.0 (2021-11-11) - - -### Features - -* **Navigation:** Added exemple with third level ([#6564](https://github.com/patternfly/patternfly-react/issues/6564)) ([c30da53](https://github.com/patternfly/patternfly-react/commit/c30da532855118f705c8cfc87c545bb1eea11ebb)) - - - - - -# 4.22.0 (2021-11-11) - - -### Features - -* enhance type correctness of CodeEditor ([#6579](https://github.com/patternfly/patternfly-react/issues/6579)) ([e1ad65c](https://github.com/patternfly/patternfly-react/commit/e1ad65c225968d5a9c74019d19e4a3c5e2666926)) - - - - - -## 4.21.4 (2021-11-10) - - -### Bug Fixes - -* **jumplinks:** fixed to always set clicked item as active ([#6542](https://github.com/patternfly/patternfly-react/issues/6542)) ([845c98f](https://github.com/patternfly/patternfly-react/commit/845c98f5f3df8aa9b6acc190707c5f1d7bf3ca38)) - - - - - -## 4.21.3 (2021-11-10) - - -### Bug Fixes - -* **Menu:** stop passing disableHover to DrilldownMenu DOM ([#6571](https://github.com/patternfly/patternfly-react/issues/6571)) ([63dcf25](https://github.com/patternfly/patternfly-react/commit/63dcf256723848ff3789828fc0a5f86d5009fc87)) - - - - - -## 4.21.2 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.21.1 (2021-11-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.21.0 (2021-11-09) - - -### Features - -* **Table:** set default sort direction ([#6544](https://github.com/patternfly/patternfly-react/issues/6544)) ([9ee4942](https://github.com/patternfly/patternfly-react/commit/9ee49428c8e1041721f2a09f8176a5aba3335049)) - - - - - -## 4.20.4 (2021-11-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.20.3 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.20.2 (2021-11-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.20.1 (2021-11-08) - - -### Bug Fixes - -* **acccessconsoles:** use object type Select options values in order to not mix displayed text with option keys ([#6496](https://github.com/patternfly/patternfly-react/issues/6496)) ([975c8e1](https://github.com/patternfly/patternfly-react/commit/975c8e14d7ea8c53eb4048ea6ef73e804b3ad2be)) - - - - - -# 4.20.0 (2021-11-04) - - -### Features - -* **log-viewer:** support ANSI color ([#6519](https://github.com/patternfly/patternfly-react/issues/6519)) ([936a699](https://github.com/patternfly/patternfly-react/commit/936a699b0514a492d3c40be08932fb7bab275cce)) - - - - - -## 4.19.11 (2021-11-01) - - -### Bug Fixes - -* **AboutModal:** allow to disable FocusTrap ([#6509](https://github.com/patternfly/patternfly-react/issues/6509)) ([72536e1](https://github.com/patternfly/patternfly-react/commit/72536e1f73641ff3f19f865f08dbb41ad0ee7b9f)) - - - - - -## 4.19.10 (2021-10-29) - - -### Bug Fixes - -* **Banner:** forward props ([#6511](https://github.com/patternfly/patternfly-react/issues/6511)) ([e36c890](https://github.com/patternfly/patternfly-react/commit/e36c89077afa82340994c0e3c0fc929e601e01bc)) - - - - - -## 4.19.9 (2021-10-28) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.19.8 (2021-10-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.19.7 (2021-10-27) - - -### Bug Fixes - -* change transformer cjs package to private ([#6515](https://github.com/patternfly/patternfly-react/issues/6515)) ([efcb357](https://github.com/patternfly/patternfly-react/commit/efcb3573b71541328ce2b16caa80ce33b2a62131)) - - - - - -## 4.19.6 (2021-10-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.19.5 (2021-10-26) - - -### Bug Fixes - -* **tokens:** added check for no matching var to avoid infinite loop ([#6502](https://github.com/patternfly/patternfly-react/issues/6502)) ([99605c2](https://github.com/patternfly/patternfly-react/commit/99605c213f12490d0abe75910e05c3e6da26a1f3)) - - - - - -## 4.19.4 (2021-10-26) - - -### Bug Fixes - -* add transformer package ([#6507](https://github.com/patternfly/patternfly-react/issues/6507)) ([daffd28](https://github.com/patternfly/patternfly-react/commit/daffd2864388abe63e625f962a8b38c2b7056209)) - - - - - -## 4.19.3 (2021-10-26) - - -### Bug Fixes - -* **transformer:** publish transformer in patternfly org ([#6506](https://github.com/patternfly/patternfly-react/issues/6506)) ([b739af3](https://github.com/patternfly/patternfly-react/commit/b739af318400b41d4e9a53bdff6232ecc176916e)) - - - - - -## 4.19.2 (2021-10-26) - - -### Bug Fixes - -* **readme:** update react-core readme ([#6505](https://github.com/patternfly/patternfly-react/issues/6505)) ([d4f9a11](https://github.com/patternfly/patternfly-react/commit/d4f9a114584eea7ab67873f199e80b348886e14b)) - - - - - -## 4.19.1 (2021-10-26) - - -### Bug Fixes - -* **DualListSelector:** account for duplicate folders ([#6499](https://github.com/patternfly/patternfly-react/issues/6499)) ([e531e68](https://github.com/patternfly/patternfly-react/commit/e531e68e7adc58459b3630f5c915ed69e3021012)) - - - - - -# 4.19.0 (2021-10-26) - - -### Features - -* **toolbar:** add sticky top modifier to toolbar ([#6447](https://github.com/patternfly/patternfly-react/issues/6447)) ([fe7605a](https://github.com/patternfly/patternfly-react/commit/fe7605a67428b43ec00b3cb2117270296576737c)) - - - - - -## 4.18.1 (2021-10-26) - - -### Bug Fixes - -* **types:** SelectOptionProp made optional ([#6503](https://github.com/patternfly/patternfly-react/issues/6503)) ([716ac80](https://github.com/patternfly/patternfly-react/commit/716ac80e2414507d589ee3002fc0cea0068ae59c)) - - - - - -# 4.18.0 (2021-10-26) - - -### Features - -* **TextInputGroup:** add text input group ([#6482](https://github.com/patternfly/patternfly-react/issues/6482)) ([a02fd4f](https://github.com/patternfly/patternfly-react/commit/a02fd4fe3345245b2252ee5a261f5b1460490642)), closes [patternfly/patternfly-react#6409](https://github.com/patternfly/patternfly-react/issues/6409) - - - - - -## 4.17.4 (2021-10-26) - - -### Bug Fixes - -* **KebabToggle:** adds event to onToggle definition ([#6490](https://github.com/patternfly/patternfly-react/issues/6490)) ([0441575](https://github.com/patternfly/patternfly-react/commit/04415757917062aa13c06b34bd94ef38c2334088)) - - - - - -## 4.17.3 (2021-10-26) - - -### Bug Fixes - -* **Modal:** test clean up ([#6489](https://github.com/patternfly/patternfly-react/issues/6489)) ([c8eaa7c](https://github.com/patternfly/patternfly-react/commit/c8eaa7c838fbedb98ea0f38e4f535488040a72e2)) - - - - - -## 4.17.2 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.17.1 (2021-10-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.17.0 (2021-10-25) - - -### Features - -* **Tabs:** Added support for tab content body with padding, added tabs open and tab secondary tabs demos ([#6484](https://github.com/patternfly/patternfly-react/issues/6484)) ([0ccbe9d](https://github.com/patternfly/patternfly-react/commit/0ccbe9d1e6e0dac0730466c92a90fe2cd9f6560d)) - - - - - -## 4.16.1 (2021-10-21) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# 4.16.0 (2021-10-21) - - -### Features - -* **label:** added compact label, updated horizontal grid card demo ([#6448](https://github.com/patternfly/patternfly-react/issues/6448)) ([89e0431](https://github.com/patternfly/patternfly-react/commit/89e04317924282140606d45f2292aa3f658b4b6c)) - - - - - -## 4.15.1 (2021-10-21) - - -### Bug Fixes - -* **DescriptionListGroup:** forward props to DOM ([#6466](https://github.com/patternfly/patternfly-react/issues/6466)) ([b78e2aa](https://github.com/patternfly/patternfly-react/commit/b78e2aa9c0360ce8418f6e7b55274ea1a50de518)) - - - - - -# 4.15.0 (2021-10-20) - - -### Features - -* **Progress:** allow node titles ([#6470](https://github.com/patternfly/patternfly-react/issues/6470)) ([46d5252](https://github.com/patternfly/patternfly-react/commit/46d52523ad5111bb11729c2750abe9aeb35d9326)) - - - - - -# 4.14.0 (2021-10-20) - - -### Features - -* **DualListSelector:** add disabled flag ([#6442](https://github.com/patternfly/patternfly-react/issues/6442)) ([85e1314](https://github.com/patternfly/patternfly-react/commit/85e131435be12c2df79336e9fa56987ed3717417)) - - - - - -## 4.13.18 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## 4.13.17 (2021-10-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.15...@patternfly/react-console@4.13.16) (2021-10-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.14...@patternfly/react-console@4.13.15) (2021-10-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.13...@patternfly/react-console@4.13.14) (2021-10-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.12...@patternfly/react-console@4.13.13) (2021-10-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.11...@patternfly/react-console@4.13.12) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.10...@patternfly/react-console@4.13.11) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.9...@patternfly/react-console@4.13.10) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.8...@patternfly/react-console@4.13.9) (2021-10-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.7...@patternfly/react-console@4.13.8) (2021-10-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.6...@patternfly/react-console@4.13.7) (2021-10-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.5...@patternfly/react-console@4.13.6) (2021-10-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.4...@patternfly/react-console@4.13.5) (2021-10-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.3...@patternfly/react-console@4.13.4) (2021-10-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.2...@patternfly/react-console@4.13.3) (2021-10-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.1...@patternfly/react-console@4.13.2) (2021-10-05) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.13.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.13.0...@patternfly/react-console@4.13.1) (2021-10-05) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.13.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.12.4...@patternfly/react-console@4.13.0) (2021-10-05) - - -### Features - -* **select:** add support for right aligned menu ([#6395](https://github.com/patternfly/patternfly-react/issues/6395)) ([74a586b](https://github.com/patternfly/patternfly-react/commit/74a586b51f6f7100f28f976d5f822b4874e6b7f4)) - - - - - -## [4.12.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.12.3...@patternfly/react-console@4.12.4) (2021-10-05) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.12.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.12.2...@patternfly/react-console@4.12.3) (2021-10-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.12.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.12.1...@patternfly/react-console@4.12.2) (2021-10-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.12.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.12.0...@patternfly/react-console@4.12.1) (2021-09-30) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.12.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.47...@patternfly/react-console@4.12.0) (2021-09-29) - - -### Features - -* **JumpLinks:** Added toggle text ([#6347](https://github.com/patternfly/patternfly-react/issues/6347)) ([36042f6](https://github.com/patternfly/patternfly-react/commit/36042f679880f819afd26618797167a42f5fe901)) - - - - - -## [4.11.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.46...@patternfly/react-console@4.11.47) (2021-09-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.45...@patternfly/react-console@4.11.46) (2021-09-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.44...@patternfly/react-console@4.11.45) (2021-09-24) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.43...@patternfly/react-console@4.11.44) (2021-09-22) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.42...@patternfly/react-console@4.11.43) (2021-09-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.41...@patternfly/react-console@4.11.42) (2021-09-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.40...@patternfly/react-console@4.11.41) (2021-09-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.39...@patternfly/react-console@4.11.40) (2021-09-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.38...@patternfly/react-console@4.11.39) (2021-09-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.37...@patternfly/react-console@4.11.38) (2021-09-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.36...@patternfly/react-console@4.11.37) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.35...@patternfly/react-console@4.11.36) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.34...@patternfly/react-console@4.11.35) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.33...@patternfly/react-console@4.11.34) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.32...@patternfly/react-console@4.11.33) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.31...@patternfly/react-console@4.11.32) (2021-09-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.30...@patternfly/react-console@4.11.31) (2021-09-10) - - -### Bug Fixes - -* **dual-list-selector:** added support for list item row, bumped core ([#6294](https://github.com/patternfly/patternfly-react/issues/6294)) ([010efb5](https://github.com/patternfly/patternfly-react/commit/010efb51c46740bd1e28866d6b956c363819b69d)) -* **SelectToggle:** use aria-label prop ([#6271](https://github.com/patternfly/patternfly-react/issues/6271)) ([5084a46](https://github.com/patternfly/patternfly-react/commit/5084a46531c8d3054e0c8b53f921d18bfb116973)) - - - - - -## [4.11.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.29...@patternfly/react-console@4.11.30) (2021-09-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.28...@patternfly/react-console@4.11.29) (2021-09-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.27...@patternfly/react-console@4.11.28) (2021-09-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.26...@patternfly/react-console@4.11.27) (2021-08-31) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.25...@patternfly/react-console@4.11.26) (2021-08-31) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.24...@patternfly/react-console@4.11.25) (2021-08-30) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.23...@patternfly/react-console@4.11.24) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.22...@patternfly/react-console@4.11.23) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.21...@patternfly/react-console@4.11.22) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.20...@patternfly/react-console@4.11.21) (2021-08-23) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.19...@patternfly/react-console@4.11.20) (2021-08-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.18...@patternfly/react-console@4.11.19) (2021-08-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.17...@patternfly/react-console@4.11.18) (2021-08-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.16...@patternfly/react-console@4.11.17) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.15...@patternfly/react-console@4.11.16) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.14...@patternfly/react-console@4.11.15) (2021-08-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.13...@patternfly/react-console@4.11.14) (2021-08-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.12...@patternfly/react-console@4.11.13) (2021-08-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.11...@patternfly/react-console@4.11.12) (2021-08-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.10...@patternfly/react-console@4.11.11) (2021-08-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.9...@patternfly/react-console@4.11.10) (2021-08-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.8...@patternfly/react-console@4.11.9) (2021-08-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.7...@patternfly/react-console@4.11.8) (2021-08-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.6...@patternfly/react-console@4.11.7) (2021-08-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.5...@patternfly/react-console@4.11.6) (2021-08-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.4...@patternfly/react-console@4.11.5) (2021-08-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.3...@patternfly/react-console@4.11.4) (2021-08-03) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.2...@patternfly/react-console@4.11.3) (2021-08-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.1...@patternfly/react-console@4.11.2) (2021-08-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.11.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.11.0...@patternfly/react-console@4.11.1) (2021-08-02) - - -### Bug Fixes - -* **Select:** first new item focused after view more clicked ([#6095](https://github.com/patternfly/patternfly-react/issues/6095)) ([a03497d](https://github.com/patternfly/patternfly-react/commit/a03497d2dd748b8d16c140f8c33352d8c343bded)) - - - - - -# [4.11.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.32...@patternfly/react-console@4.11.0) (2021-07-30) - - -### Features - -* **ExpandableSection:** Added props to support disclosure variation ([#6078](https://github.com/patternfly/patternfly-react/issues/6078)) ([3e9aa7e](https://github.com/patternfly/patternfly-react/commit/3e9aa7eb985b560c8c899c00f1ced4b0221aded4)) - - - - - -## [4.10.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.31...@patternfly/react-console@4.10.32) (2021-07-29) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.30...@patternfly/react-console@4.10.31) (2021-07-29) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.29...@patternfly/react-console@4.10.30) (2021-07-28) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.28...@patternfly/react-console@4.10.29) (2021-07-28) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.27...@patternfly/react-console@4.10.28) (2021-07-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.26...@patternfly/react-console@4.10.27) (2021-07-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.25...@patternfly/react-console@4.10.26) (2021-07-23) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.24...@patternfly/react-console@4.10.25) (2021-07-21) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.23...@patternfly/react-console@4.10.24) (2021-07-21) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.22...@patternfly/react-console@4.10.23) (2021-07-21) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.21...@patternfly/react-console@4.10.22) (2021-07-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.20...@patternfly/react-console@4.10.21) (2021-07-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.19...@patternfly/react-console@4.10.20) (2021-07-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.18...@patternfly/react-console@4.10.19) (2021-07-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.17...@patternfly/react-console@4.10.18) (2021-07-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.16...@patternfly/react-console@4.10.17) (2021-07-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.15...@patternfly/react-console@4.10.16) (2021-07-14) - - -### Bug Fixes - -* **VncConsole:** persist rfc instance in VncConsole ([#6012](https://github.com/patternfly/patternfly-react/issues/6012)) ([2e21929](https://github.com/patternfly/patternfly-react/commit/2e21929ee91b4d92d5a7754a14c46c06202963f7)) - - - - - -## [4.10.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.14...@patternfly/react-console@4.10.15) (2021-07-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.13...@patternfly/react-console@4.10.14) (2021-07-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.12...@patternfly/react-console@4.10.13) (2021-07-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.11...@patternfly/react-console@4.10.12) (2021-07-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.10...@patternfly/react-console@4.10.11) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.9...@patternfly/react-console@4.10.10) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.8...@patternfly/react-console@4.10.9) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.7...@patternfly/react-console@4.10.8) (2021-07-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.6...@patternfly/react-console@4.10.7) (2021-07-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.5...@patternfly/react-console@4.10.6) (2021-07-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.4...@patternfly/react-console@4.10.5) (2021-07-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.3...@patternfly/react-console@4.10.4) (2021-07-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.2...@patternfly/react-console@4.10.3) (2021-06-30) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.10.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.1...@patternfly/react-console@4.10.2) (2021-06-30) - - -### Bug Fixes - -* **ci:** change master branch to main ([4ac4129](https://github.com/patternfly/patternfly-react/commit/4ac4129e8da9a37367ea7612019f8d7af1ed8836)) - - - - - -## [4.10.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.10.0...@patternfly/react-console@4.10.1) (2021-06-28) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.10.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.9.5...@patternfly/react-console@4.10.0) (2021-06-21) - - -### Features - -* **LogViewer:** Make logviewer responsive and change search result styling ([#5927](https://github.com/patternfly/patternfly-react/issues/5927)) ([3f6a493](https://github.com/patternfly/patternfly-react/commit/3f6a4934127d23de1baf2447003296600d9f3c5b)) - - - - - -## [4.9.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.9.4...@patternfly/react-console@4.9.5) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.9.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.9.3...@patternfly/react-console@4.9.4) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.9.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.9.2...@patternfly/react-console@4.9.3) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.9.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.9.1...@patternfly/react-console@4.9.2) (2021-06-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.9.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.9.0...@patternfly/react-console@4.9.1) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.9.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.26...@patternfly/react-console@4.9.0) (2021-06-17) - - -### Features - -* **DualListSelector:** add tooltips to control buttons ([#5914](https://github.com/patternfly/patternfly-react/issues/5914)) ([1292479](https://github.com/patternfly/patternfly-react/commit/1292479e121f4eeaadb2f6954b24b0e68551dcd3)) - - - - - -## [4.8.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.25...@patternfly/react-console@4.8.26) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.24...@patternfly/react-console@4.8.25) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.23...@patternfly/react-console@4.8.24) (2021-06-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.22...@patternfly/react-console@4.8.23) (2021-06-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.21...@patternfly/react-console@4.8.22) (2021-06-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.20...@patternfly/react-console@4.8.21) (2021-06-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.19...@patternfly/react-console@4.8.20) (2021-06-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.18...@patternfly/react-console@4.8.19) (2021-06-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.17...@patternfly/react-console@4.8.18) (2021-06-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.16...@patternfly/react-console@4.8.17) (2021-06-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.15...@patternfly/react-console@4.8.16) (2021-06-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.14...@patternfly/react-console@4.8.15) (2021-06-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.13...@patternfly/react-console@4.8.14) (2021-06-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.12...@patternfly/react-console@4.8.13) (2021-06-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.11...@patternfly/react-console@4.8.12) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.10...@patternfly/react-console@4.8.11) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.9...@patternfly/react-console@4.8.10) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.8...@patternfly/react-console@4.8.9) (2021-05-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.7...@patternfly/react-console@4.8.8) (2021-05-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.6...@patternfly/react-console@4.8.7) (2021-05-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.5...@patternfly/react-console@4.8.6) (2021-05-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.4...@patternfly/react-console@4.8.5) (2021-05-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.3...@patternfly/react-console@4.8.4) (2021-05-24) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.2...@patternfly/react-console@4.8.3) (2021-05-21) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.1...@patternfly/react-console@4.8.2) (2021-05-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.8.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.8.0...@patternfly/react-console@4.8.1) (2021-05-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.8.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.7.3...@patternfly/react-console@4.8.0) (2021-05-13) - - -### Features - -* **Select:** Added footer and view more options ([#5736](https://github.com/patternfly/patternfly-react/issues/5736)) ([607c436](https://github.com/patternfly/patternfly-react/commit/607c436cf840fce9f3db923135fede361bcd02c2)) - - - - - -## [4.7.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.7.2...@patternfly/react-console@4.7.3) (2021-05-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.7.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.7.1...@patternfly/react-console@4.7.2) (2021-05-11) - - -### Bug Fixes - -* **togglegroup:** remove dividers, light variation, add compact ([#5762](https://github.com/patternfly/patternfly-react/issues/5762)) ([d5c8c31](https://github.com/patternfly/patternfly-react/commit/d5c8c31bb24f613687fcf5aa3213ee51a8007580)) - - - - - -## [4.7.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.7.0...@patternfly/react-console@4.7.1) (2021-05-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.7.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.15...@patternfly/react-console@4.7.0) (2021-05-10) - - -### Features - -* **Select:** Add flag to accept input values even if not in menu ([#5751](https://github.com/patternfly/patternfly-react/issues/5751)) ([6373bbf](https://github.com/patternfly/patternfly-react/commit/6373bbf3a1824424ebc54a13b154259da2aa6a54)) - - - - - -## [4.6.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.14...@patternfly/react-console@4.6.15) (2021-05-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.13...@patternfly/react-console@4.6.14) (2021-05-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.12...@patternfly/react-console@4.6.13) (2021-05-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.11...@patternfly/react-console@4.6.12) (2021-05-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.10...@patternfly/react-console@4.6.11) (2021-05-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.9...@patternfly/react-console@4.6.10) (2021-05-06) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.8...@patternfly/react-console@4.6.9) (2021-05-05) - - -### Bug Fixes - -* **packages:** check canUseDOM before using DOM ([#5733](https://github.com/patternfly/patternfly-react/issues/5733)) ([915f03e](https://github.com/patternfly/patternfly-react/commit/915f03e7b8107a2767cc0df9bc72ba7364524d5e)) - - - - - -## [4.6.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.7...@patternfly/react-console@4.6.8) (2021-05-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.6...@patternfly/react-console@4.6.7) (2021-05-03) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.5...@patternfly/react-console@4.6.6) (2021-05-03) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.4...@patternfly/react-console@4.6.5) (2021-05-03) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.3...@patternfly/react-console@4.6.4) (2021-04-29) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.2...@patternfly/react-console@4.6.3) (2021-04-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.1...@patternfly/react-console@4.6.2) (2021-04-22) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.6.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.6.0...@patternfly/react-console@4.6.1) (2021-04-21) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.6.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.5.4...@patternfly/react-console@4.6.0) (2021-04-20) - - -### Features - -* **Select:** Added invalid state to select ([#5675](https://github.com/patternfly/patternfly-react/issues/5675)) ([d222162](https://github.com/patternfly/patternfly-react/commit/d222162565605b4776b31901773827459bc2d9b5)) - - - - - -## [4.5.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.5.3...@patternfly/react-console@4.5.4) (2021-04-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.5.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.5.2...@patternfly/react-console@4.5.3) (2021-04-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.5.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.5.1...@patternfly/react-console@4.5.2) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.5.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.5.0...@patternfly/react-console@4.5.1) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.5.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.4.3...@patternfly/react-console@4.5.0) (2021-04-16) - - -### Features - -* **Table:** Add optional icons to tree table rows, add responsive view ([#5672](https://github.com/patternfly/patternfly-react/issues/5672)) ([7ecba96](https://github.com/patternfly/patternfly-react/commit/7ecba96a191798d01c7f9209a14a04f4a658d7bb)) - - - - - -## [4.4.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.4.2...@patternfly/react-console@4.4.3) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.4.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.4.1...@patternfly/react-console@4.4.2) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.4.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.4.0...@patternfly/react-console@4.4.1) (2021-04-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.40...@patternfly/react-console@4.4.0) (2021-04-15) - - -### Features - -* **ExpandableSection:** add detached variant, update tests ([#5643](https://github.com/patternfly/patternfly-react/issues/5643)) ([28bea0a](https://github.com/patternfly/patternfly-react/commit/28bea0afd738e5f0b9b656b0dac3920e2f1c5c9e)) - - - - - -## [4.3.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.39...@patternfly/react-console@4.3.40) (2021-04-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.38...@patternfly/react-console@4.3.39) (2021-04-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.37...@patternfly/react-console@4.3.38) (2021-04-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.36...@patternfly/react-console@4.3.37) (2021-04-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.35...@patternfly/react-console@4.3.36) (2021-04-14) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.34...@patternfly/react-console@4.3.35) (2021-04-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.33...@patternfly/react-console@4.3.34) (2021-04-13) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.32...@patternfly/react-console@4.3.33) (2021-04-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.31...@patternfly/react-console@4.3.32) (2021-04-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.30...@patternfly/react-console@4.3.31) (2021-04-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.29...@patternfly/react-console@4.3.30) (2021-04-05) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.28...@patternfly/react-console@4.3.29) (2021-04-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.27...@patternfly/react-console@4.3.28) (2021-03-29) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.26...@patternfly/react-console@4.3.27) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.25...@patternfly/react-console@4.3.26) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.24...@patternfly/react-console@4.3.25) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.23...@patternfly/react-console@4.3.24) (2021-03-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.22...@patternfly/react-console@4.3.23) (2021-03-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.21...@patternfly/react-console@4.3.22) (2021-03-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.20...@patternfly/react-console@4.3.21) (2021-03-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.19...@patternfly/react-console@4.3.20) (2021-03-24) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.18...@patternfly/react-console@4.3.19) (2021-03-22) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.17...@patternfly/react-console@4.3.18) (2021-03-22) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.16...@patternfly/react-console@4.3.17) (2021-03-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.15...@patternfly/react-console@4.3.16) (2021-03-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.14...@patternfly/react-console@4.3.15) (2021-03-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.13...@patternfly/react-console@4.3.14) (2021-03-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.12...@patternfly/react-console@4.3.13) (2021-03-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.11...@patternfly/react-console@4.3.12) (2021-03-05) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.10...@patternfly/react-console@4.3.11) (2021-03-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.9...@patternfly/react-console@4.3.10) (2021-03-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.8...@patternfly/react-console@4.3.9) (2021-03-04) - - -### Bug Fixes - -* **searchinput:** add searchInputMenuBody class ([#5518](https://github.com/patternfly/patternfly-react/issues/5518)) ([99f0512](https://github.com/patternfly/patternfly-react/commit/99f05123d28a7be887efd1921733fc2dc0bddd6d)) - - - - - -## [4.3.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.7...@patternfly/react-console@4.3.8) (2021-03-03) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.6...@patternfly/react-console@4.3.7) (2021-03-03) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.5...@patternfly/react-console@4.3.6) (2021-03-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.4...@patternfly/react-console@4.3.5) (2021-03-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.3...@patternfly/react-console@4.3.4) (2021-02-24) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.2...@patternfly/react-console@4.3.3) (2021-02-18) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.1...@patternfly/react-console@4.3.2) (2021-02-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.3.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.3.0...@patternfly/react-console@4.3.1) (2021-02-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.3.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.31...@patternfly/react-console@4.3.0) (2021-02-12) - - -### Features - -* **Slider:** Added touch support ([#5453](https://github.com/patternfly/patternfly-react/issues/5453)) ([32ce723](https://github.com/patternfly/patternfly-react/commit/32ce7238d8743f6d4a5f7b128b1293e855d012ca)) - - - - - -## [4.2.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.30...@patternfly/react-console@4.2.31) (2021-02-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.29...@patternfly/react-console@4.2.30) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.28...@patternfly/react-console@4.2.29) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.27...@patternfly/react-console@4.2.28) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.26...@patternfly/react-console@4.2.27) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.25...@patternfly/react-console@4.2.26) (2021-02-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.24...@patternfly/react-console@4.2.25) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.23...@patternfly/react-console@4.2.24) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.22...@patternfly/react-console@4.2.23) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.21...@patternfly/react-console@4.2.22) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.20...@patternfly/react-console@4.2.21) (2021-02-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.19...@patternfly/react-console@4.2.20) (2021-02-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.18...@patternfly/react-console@4.2.19) (2021-02-03) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.17...@patternfly/react-console@4.2.18) (2021-02-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.16...@patternfly/react-console@4.2.17) (2021-02-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.15...@patternfly/react-console@4.2.16) (2021-02-01) - - -### Bug Fixes - -* **Select:** adjust Select component so that it also works with children changes while it's mounted ([#5375](https://github.com/patternfly/patternfly-react/issues/5375)) ([227da1d](https://github.com/patternfly/patternfly-react/commit/227da1dca3fdd108d411bb42c5021f0af3540fe9)), closes [#5365](https://github.com/patternfly/patternfly-react/issues/5365) [#5374](https://github.com/patternfly/patternfly-react/issues/5374) - - - - - -## [4.2.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.14...@patternfly/react-console@4.2.15) (2021-01-27) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.13...@patternfly/react-console@4.2.14) (2021-01-26) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.12...@patternfly/react-console@4.2.13) (2021-01-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.11...@patternfly/react-console@4.2.12) (2021-01-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.10...@patternfly/react-console@4.2.11) (2021-01-25) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.9...@patternfly/react-console@4.2.10) (2021-01-22) - - -### Bug Fixes - -* **Drawer:** initial width doesn't respect min/max widths ([#5313](https://github.com/patternfly/patternfly-react/issues/5313)) ([4f199c4](https://github.com/patternfly/patternfly-react/commit/4f199c4db5c3cb493d2947d871f687cc5527517c)) - - - - - -## [4.2.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.8...@patternfly/react-console@4.2.9) (2021-01-22) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.7...@patternfly/react-console@4.2.8) (2021-01-19) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.6...@patternfly/react-console@4.2.7) (2021-01-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.5...@patternfly/react-console@4.2.6) (2021-01-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.4...@patternfly/react-console@4.2.5) (2021-01-12) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.3...@patternfly/react-console@4.2.4) (2021-01-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.2...@patternfly/react-console@4.2.3) (2021-01-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.1...@patternfly/react-console@4.2.2) (2021-01-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.2.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.2.0...@patternfly/react-console@4.2.1) (2021-01-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.2.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.32...@patternfly/react-console@4.2.0) (2021-01-06) - - -### Features - -* **packages:** use react 17 ([#5111](https://github.com/patternfly/patternfly-react/issues/5111)) ([7fbafcc](https://github.com/patternfly/patternfly-react/commit/7fbafcc947c95d2bda2f4fad8f7737cf7dd3fca6)) - - - - - -## [4.1.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.31...@patternfly/react-console@4.1.32) (2021-01-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.30...@patternfly/react-console@4.1.31) (2021-01-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.29...@patternfly/react-console@4.1.30) (2021-01-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.28...@patternfly/react-console@4.1.29) (2020-12-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.27...@patternfly/react-console@4.1.28) (2020-12-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.26...@patternfly/react-console@4.1.27) (2020-12-15) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.25...@patternfly/react-console@4.1.26) (2020-12-11) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.24...@patternfly/react-console@4.1.25) (2020-12-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.23...@patternfly/react-console@4.1.24) (2020-12-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.22...@patternfly/react-console@4.1.23) (2020-12-10) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.21...@patternfly/react-console@4.1.22) (2020-12-09) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.20...@patternfly/react-console@4.1.21) (2020-12-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.19...@patternfly/react-console@4.1.20) (2020-12-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.18...@patternfly/react-console@4.1.19) (2020-12-08) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.17...@patternfly/react-console@4.1.18) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.16...@patternfly/react-console@4.1.17) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.15...@patternfly/react-console@4.1.16) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.14...@patternfly/react-console@4.1.15) (2020-12-07) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.13...@patternfly/react-console@4.1.14) (2020-12-04) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.12...@patternfly/react-console@4.1.13) (2020-12-03) - - -### Bug Fixes - -* **VncConsole:** replace novnc-core usage with the original @novnc/novnc ([#5208](https://github.com/patternfly/patternfly-react/issues/5208)) ([6c4c0c2](https://github.com/patternfly/patternfly-react/commit/6c4c0c2e981088e9220b834e2520063fce9d024e)), closes [#5157](https://github.com/patternfly/patternfly-react/issues/5157) - - - - - -## [4.1.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.11...@patternfly/react-console@4.1.12) (2020-12-02) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.10...@patternfly/react-console@4.1.11) (2020-12-01) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.9...@patternfly/react-console@4.1.10) (2020-11-30) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.8...@patternfly/react-console@4.1.9) (2020-11-30) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.7...@patternfly/react-console@4.1.8) (2020-11-23) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.6...@patternfly/react-console@4.1.7) (2020-11-20) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.5...@patternfly/react-console@4.1.6) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.4...@patternfly/react-console@4.1.5) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.3...@patternfly/react-console@4.1.4) (2020-11-17) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -## [4.1.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.2...@patternfly/react-console@4.1.3) (2020-11-17) - - -### Bug Fixes - -* **console:** remove css imports ([#5147](https://github.com/patternfly/patternfly-react/issues/5147)) ([df3e2eb](https://github.com/patternfly/patternfly-react/commit/df3e2ebd1eb478ef7b1e48f3c8237c5cc398df4c)) - - - - - -## [4.1.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.1...@patternfly/react-console@4.1.2) (2020-11-16) - - -### Bug Fixes - -* **datepicker:** add calendar component ([#5026](https://github.com/patternfly/patternfly-react/issues/5026)) ([198dd0f](https://github.com/patternfly/patternfly-react/commit/198dd0fc202bdfa55ef9c9cc1a6721778f1dd265)) - - - - - -## [4.1.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@4.1.0...@patternfly/react-console@4.1.1) (2020-11-16) - -**Note:** Version bump only for package @patternfly/react-console - - - - - -# [4.1.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-console@2.0.13...@patternfly/react-console@4.1.0) (2020-11-13) - - -### Features - -* **packages:** bump Victory package ([#5116](https://github.com/patternfly/patternfly-react/issues/5116)) ([a4645a2](https://github.com/patternfly/patternfly-react/commit/a4645a2fa14b2742e8957b1ae579f4350e3ddbd4)) diff --git a/packages/react-console/README.md b/packages/react-console/README.md deleted file mode 100644 index 612e3abe2ae..00000000000 --- a/packages/react-console/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# @patternfly/react-console - -This package provides VncConsole, SerialConsole and DesktopViewer React components -to be used alongside patternfly-react to access virtual machine or server consoles. - -### Prerequisite - -#### Node Environment - -This project currently supports Node [Active LTS](https://github.com/nodejs/Release#release-schedule) releases. Please stay current with Node Active LTS when developing patternfly-react. - -For example, to develop with Node 8, use the following: - -``` -nvm install 8 -nvm use 8 -``` - -This project also requires a Yarn version of >=1.6.0. The latest version can be installed [here](https://yarnpkg.com/). - -### Installing - -``` -yarn add @patternfly/react-console -``` - -or - -``` -npm install @patternfly/react-console --save -``` - -### Usage - -#### Pre-requisites - -It's strongly advised to use the PatternFly Base CSS in your whole project, or some components may diverge in appearance: - -```js -import '@patternfly/react-core/dist/styles/base.css'; -``` - -```js -import { VncConsole, SerialConsole } from '@patternfly/react-console'; -``` - -# Documentation - -This project uses Gatsby. For an overview of the project structure please refer to the [Gatsby documentation - Building with Components](https://www.gatsbyjs.org/docs/building-with-components/). - -A comprehensive list of components and detailed usage of each can be found on the [PatternFly React Docs][docs] website -You can also find how each component is meant to be used from a design perspective on the [PatternFly 4 Core][patternfly-4] website. - -Note: All commands below assume you are on the root directory in this repository. - -### Install - -Run to install all the dependencies - -```sh -yarn && yarn bootstrap && yarn build && yarn build:docs -``` - -### Running - -To start the site locally. - -```sh -yarn build && yarn start:pf4 -``` - -### Building - -To build the site. - -```sh -yarn build:docs -``` - -# Contributing Components - -This library makes use of the babel plugin from [@patternfly/react-styles](../react-styles/README.md) to enable providing the CSS alongside the components. This removes the need for consumers to use (style|css|sass)-loaders. For any CSS not provided by core please use the `StyleSheet.create` utility from [@patternfly/react-styles](../react-styles/README.md). This will prevent collisions with any consumers, and allow the CSS to be bundled with the component. - -### Building - -``` -yarn build -``` - -Note the build scripts for this are located in the root package.json under `yarn build`. - -[patternfly-4]: https://github.com/patternfly/patternfly -[docs]: https://patternfly-react.surge.sh/ diff --git a/packages/react-console/node-sass-patternfly-importer.js b/packages/react-console/node-sass-patternfly-importer.js deleted file mode 100644 index 5d65b3aa318..00000000000 --- a/packages/react-console/node-sass-patternfly-importer.js +++ /dev/null @@ -1,14 +0,0 @@ -const path = require('path'); - -/** - * @param {string} url - Url string - */ -function importer(url) { - // Assume yarn hoists these. - if (url.startsWith('~')) { - url = path.join(__dirname, `../../node_modules/${url.substr(1)}`); - } - return { file: url }; -} - -module.exports = importer; diff --git a/packages/react-console/package.json b/packages/react-console/package.json deleted file mode 100644 index 99d740a4403..00000000000 --- a/packages/react-console/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@patternfly/react-console", - "version": "4.39.0", - "description": "This package provides VncConsole, SerialConsole and DesktopViewer React components to be used alongside patternfly-react to access virtual machine or server consoles.", - "main": "dist/js/index.js", - "module": "dist/esm/index.js", - "types": "dist/esm/index.d.ts", - "patternfly:src": "src/", - "sideEffects": [ - "*.css" - ], - "publishConfig": { - "access": "public", - "tag": "prerelease" - }, - "repository": { - "type": "git", - "url": "https://github.com/patternfly/patternfly-react.git" - }, - "keywords": [ - "react", - "patternfly", - "console" - ], - "author": "Red Hat", - "license": "MIT", - "bugs": { - "url": "https://github.com/patternfly/patternfly-react/issues" - }, - "homepage": "https://github.com/patternfly/patternfly-react/tree/main/packages/react-console#readme", - "scripts": { - "clean": "rimraf dist" - }, - "dependencies": { - "@novnc/novnc": "^1.2.0", - "@patternfly/patternfly": "4.166.4", - "@patternfly/react-core": "^4.188.0", - "@spice-project/spice-html5": "^0.2.1", - "@types/file-saver": "^2.0.1", - "file-saver": "^1.3.8", - "tslib": "^2.0.0", - "xterm": "^4.8.1", - "xterm-addon-fit": "^0.2.1" - }, - "devDependencies": { - "rimraf": "^2.6.2", - "typescript": "^4.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - } -} diff --git a/packages/react-console/src/components/AccessConsoles/AccessConsoles.tsx b/packages/react-console/src/components/AccessConsoles/AccessConsoles.tsx deleted file mode 100644 index 6637c315ee4..00000000000 --- a/packages/react-console/src/components/AccessConsoles/AccessConsoles.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React from 'react'; -import { css } from '@patternfly/react-styles'; -import { Select, SelectOption, SelectOptionObject, SelectVariant } from '@patternfly/react-core'; - -import { constants } from '../common/constants'; - -import styles from '@patternfly/react-styles/css/components/Consoles/AccessConsoles'; -import '@patternfly/react-styles/css/components/Consoles/AccessConsoles.css'; - -const { NONE_TYPE, SERIAL_CONSOLE_TYPE, VNC_CONSOLE_TYPE, DESKTOP_VIEWER_CONSOLE_TYPE } = constants; - -const getChildTypeName = (child: any) => - child && child.props && child.props.type ? child.props.type : (child && child.type && child.type.displayName) || null; - -const isChildOfType = (child: any, type: string) => { - if (child && child.props && child.props.type) { - return child.props.type === type; - } else if (child && child.type) { - return child.type.displayName === type; - } - return false; -}; - -export interface AccessConsolesProps { - /** - * Child element can be either - * - , or - * - or has a property "type" of value either SERIAL_CONSOLE_TYPE or VNC_CONSOLE_TYPE (useful when wrapping (composing) basic console components - */ - children?: React.ReactElement[] | React.ReactNode; - /** Placeholder text for the console selection */ - textSelectConsoleType?: string; - /** The value for the Serial Console option. This can be overriden by the type property of the child component */ - textSerialConsole?: string; - /** The value for the VNC Console option. This can be overriden by the type property of the child component */ - textVncConsole?: string; - /** The value for the Desktop Viewer Console option. This can be overriden by the type property of the child component */ - textDesktopViewerConsole?: string; - /** Initial selection of the Select */ - preselectedType?: string; // NONE_TYPE | SERIAL_CONSOLE_TYPE | VNC_CONSOLE_TYPE | DESKTOP_VIEWER_CONSOLE_TYPE; -} - -export const AccessConsoles: React.FunctionComponent = ({ - children, - textSelectConsoleType = 'Select console type', - textSerialConsole = 'Serial console', - textVncConsole = 'VNC console', - textDesktopViewerConsole = 'Desktop viewer', - preselectedType = null -}) => { - const typeMap = { - [SERIAL_CONSOLE_TYPE]: textSerialConsole, - [VNC_CONSOLE_TYPE]: textVncConsole, - [DESKTOP_VIEWER_CONSOLE_TYPE]: textDesktopViewerConsole - }; - const [type, setType] = React.useState( - preselectedType !== NONE_TYPE - ? ({ value: preselectedType, toString: () => typeMap[preselectedType] } as SelectOptionObject) - : null - ); - const [isOpen, setIsOpen] = React.useState(false); - - const getConsoleForType = (type: any) => - React.Children.map(children as React.ReactElement[], (child: any) => { - if (getChildTypeName(child) === type.value) { - return {child}; - } else { - return null; - } - }); - - const onToggle = (isOpen: boolean) => { - setIsOpen(isOpen); - }; - - const selectOptions: any[] = []; - - React.Children.toArray(children as React.ReactElement[]).forEach((child: any) => { - if (isChildOfType(child, VNC_CONSOLE_TYPE)) { - selectOptions.push( - textVncConsole } as SelectOptionObject} - /> - ); - } else if (isChildOfType(child, SERIAL_CONSOLE_TYPE)) { - selectOptions.push( - textSerialConsole } as SelectOptionObject} - /> - ); - } else if (isChildOfType(child, DESKTOP_VIEWER_CONSOLE_TYPE)) { - selectOptions.push( - textDesktopViewerConsole } as SelectOptionObject} - /> - ); - } else { - const typeText = getChildTypeName(child); - selectOptions.push( - typeText } as SelectOptionObject} - /> - ); - } - }); - return ( -
    - {React.Children.toArray(children).length > 1 && ( -
    - -
    - )} - {type && getConsoleForType(type)} -
    - ); -}; -AccessConsoles.displayName = 'AccessConsoles'; diff --git a/packages/react-console/src/components/AccessConsoles/__tests__/AccessConsole.test.tsx b/packages/react-console/src/components/AccessConsoles/__tests__/AccessConsole.test.tsx deleted file mode 100644 index 301a499d6eb..00000000000 --- a/packages/react-console/src/components/AccessConsoles/__tests__/AccessConsole.test.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; - -import { AccessConsoles } from '../AccessConsoles'; -import { SerialConsole } from '../../SerialConsole'; -import { VncConsole } from '../../VncConsole'; -import { DesktopViewer } from '../../DesktopViewer'; -import { constants } from '../../common/constants'; - -const { SERIAL_CONSOLE_TYPE, VNC_CONSOLE_TYPE, LOADING } = constants; - -const MyVncConsoleTestWrapper = () =>

    This can be VncConsole component or a wrapper

    ; - -const vnc = { - address: 'my.host.com', - port: 5902, - tlsPort: '5903' -}; - -test('AccessConsoles with SerialConsole as a single child', () => { - const view = shallow( - - - - ); - expect(view).toMatchSnapshot(); -}); - -test('AccessConsoles with VncConsole as a single child', () => { - const view = shallow( - - - - ); - expect(view).toMatchSnapshot(); -}); - -test('AccessConsoles with SerialConsole and VncConsole as children', () => { - const view = shallow( - - - - - ); - expect(view).toMatchSnapshot(); -}); - -const SerialConsoleConnected = () => ( -

    - Whatever component, preferably wrapping SerialConsole with callbacks adapted to a particular backend. -

    -); - -test('AccessConsoles with wrapped SerialConsole as a child', () => { - const view = shallow( - - - - ); - expect(view).toMatchSnapshot(); -}); - -test('AccessConsoles with preselected SerialConsole', () => { - const wrapper = mount( - - - - ); - expect(wrapper).toMatchSnapshot(); - expect(wrapper.find('SerialConsoleConnected')).toHaveLength(1); -}); - -test('AccessConsoles switching SerialConsole and VncConsole', () => { - const wrapper = mount( - - - - - ); - - expect(wrapper).toMatchSnapshot(); - expect(wrapper.find('SerialConsole')).toHaveLength(0); - expect(wrapper.find('MyVncConsoleTestWrapper')).toHaveLength(0); - - const button = wrapper.find('button#pf-c-console__type-selector'); - button.simulate('click'); - expect(wrapper.find('SerialConsole')).toHaveLength(0); - - let consoleItems = wrapper.find('ul li'); - expect(consoleItems).toHaveLength(2); - consoleItems - .at(1) - .find('button') - .simulate('click'); - expect(consoleItems).toMatchSnapshot(); - expect(wrapper.find('SerialConsole')).toHaveLength(1); - expect(wrapper.find('MyVncConsoleTestWrapper')).toHaveLength(0); - - button.simulate('click'); - consoleItems = wrapper.find('ul li'); - expect(consoleItems).toHaveLength(2); - consoleItems - .at(0) - .find('button') - .simulate('click'); - expect(consoleItems).toMatchSnapshot(); - expect(wrapper.find('SerialConsole')).toHaveLength(0); - expect(wrapper.find('MyVncConsoleTestWrapper')).toHaveLength(1); -}); - -test('AccessConsoles default setting', () => { - const wrapperDefault = mount( - - - - - ); - - const wrapperKeepConnection = mount( - - - - - ); - wrapperKeepConnection.find('button#pf-c-console__type-selector').simulate('click'); - wrapperKeepConnection - .find('ul li') - .first() - .find('button') - .simulate('click'); // Select SerialConsole -}); - -test('Empty AccessConsoles', () => { - const view = render(); - expect(view).toMatchSnapshot(); -}); - -test('AccessConsoles with DesktopViewer', () => { - const view = render( - - - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-console/src/components/AccessConsoles/__tests__/__snapshots__/AccessConsole.test.tsx.snap b/packages/react-console/src/components/AccessConsoles/__tests__/__snapshots__/AccessConsole.test.tsx.snap deleted file mode 100644 index 32918ea58e3..00000000000 --- a/packages/react-console/src/components/AccessConsoles/__tests__/__snapshots__/AccessConsole.test.tsx.snap +++ /dev/null @@ -1,445 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AccessConsoles switching SerialConsole and VncConsole 1`] = ` - -
    -
    - -
    -
    -
    -`; - -exports[`AccessConsoles switching SerialConsole and VncConsole 2`] = ` -Array [ - , - , -] -`; - -exports[`AccessConsoles switching SerialConsole and VncConsole 3`] = ` -Array [ - , - , -] -`; - -exports[`AccessConsoles with DesktopViewer 1`] = ` -
    -`; - -exports[`AccessConsoles with SerialConsole and VncConsole as children 1`] = ` -
    -
    - -
    -
    -`; - -exports[`AccessConsoles with SerialConsole as a single child 1`] = ` -
    -`; - -exports[`AccessConsoles with VncConsole as a single child 1`] = ` -
    -`; - -exports[`AccessConsoles with preselected SerialConsole 1`] = ` - -
    - -

    - Whatever component, preferably wrapping - - SerialConsole - - with callbacks adapted to a particular backend. -

    -
    -
    -
    -`; - -exports[`AccessConsoles with wrapped SerialConsole as a child 1`] = ` -
    -`; - -exports[`Empty AccessConsoles 1`] = ` -
    -`; diff --git a/packages/react-console/src/components/AccessConsoles/examples/AccessConsoles.md b/packages/react-console/src/components/AccessConsoles/examples/AccessConsoles.md deleted file mode 100644 index 66d90d2a0ff..00000000000 --- a/packages/react-console/src/components/AccessConsoles/examples/AccessConsoles.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: Access consoles -section: extensions -propComponents: ['AccessConsoles'] -ouia: false -beta: true ---- - -### Note -AccessConsoles lives in its own package at [`@patternfly/react-console`](https://www.npmjs.com/package/@patternfly/react-console) - -import { AccessConsoles, SerialConsole, VncConsole, DesktopViewer } from '@patternfly/react-console'; -import { SerialConsoleCustom } from './SerialConsoleCustom.jsx'; - -## Examples - -### Basic Usage -```js -import React from 'react'; -import { AccessConsoles, SerialConsole, VncConsole, DesktopViewer } from '@patternfly/react-console'; -import { SerialConsoleCustom } from './SerialConsoleCustom.jsx'; - -AccessConsolesVariants = () => { - const [status, setStatus] = React.useState('disconnected'); - const setConnected = React.useRef(debounce(() => setStatus('connected'), 3000)).current; - const ref = React.createRef(); - - return ( - - - { - setStatus('loading'); - setConnected(); - }} - status={status} - onDisconnect={() => setStatus('disconnected')} - onData={data => { - ref.current.onDataReceived(data); - }} - ref={ref} - /> - - - - ); -}; -``` - diff --git a/packages/react-console/src/components/AccessConsoles/examples/SerialConsoleCustom.jsx b/packages/react-console/src/components/AccessConsoles/examples/SerialConsoleCustom.jsx deleted file mode 100644 index 2cd4962e942..00000000000 --- a/packages/react-console/src/components/AccessConsoles/examples/SerialConsoleCustom.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import { debounce } from '@patternfly/react-core'; -import { SerialConsole } from '@patternfly/react-console'; - -export const SerialConsoleCustom = () => { - const [status, setStatus] = React.useState('disconnected'); - const setConnected = React.useRef(debounce(() => setStatus('connected'), 3000)).current; - const ref2 = React.createRef(); - - return ( - { - setStatus('loading'); - setConnected(); - }} - onDisconnect={() => setStatus('disconnected')} - onData={data => { - ref2.current.onDataReceived(data); - }} - status={status} - ref={ref2} - /> - ); -}; diff --git a/packages/react-console/src/components/AccessConsoles/index.ts b/packages/react-console/src/components/AccessConsoles/index.ts deleted file mode 100644 index d3e928afb93..00000000000 --- a/packages/react-console/src/components/AccessConsoles/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './AccessConsoles'; diff --git a/packages/react-console/src/components/DesktopViewer/ConnectWithRemoteViewer.tsx b/packages/react-console/src/components/DesktopViewer/ConnectWithRemoteViewer.tsx deleted file mode 100644 index 9ca7494cd3c..00000000000 --- a/packages/react-console/src/components/DesktopViewer/ConnectWithRemoteViewer.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import React from 'react'; -import { Button, ExpandableSection } from '@patternfly/react-core'; - -import { constants } from '../common/constants'; - -import { MoreInformationDefaultContent } from './MoreInformationDefaultContent'; -import { MoreInformationDefaultRDPContent } from './MoreInformationDefaultRDPContent'; - -import { - generateDescriptorFile, - downloadFile, - onGenerateFunctionType, - onDownloadFunctionType -} from './consoleDescriptorGenerator'; -import { ConsoleDetailPropType } from './ConsoleDetailPropType'; - -const { - VNC_CONSOLE_TYPE, - SPICE_CONSOLE_TYPE, - RDP_CONSOLE_TYPE, - DEFAULT_VV_FILENAME, - DEFAULT_VV_MIMETYPE, - DEFAULT_RDP_FILENAME, - DEFAULT_RDP_MIMETYPE -} = constants; - -export interface ConnectWithRemoteViewerProps extends React.HTMLProps { - /** Custom content of more-info section */ - children?: React.ReactNode; - - /** Connection details for Spice */ - spice?: ConsoleDetailPropType; - /** Connection details for VNC */ - vnc?: ConsoleDetailPropType; - /** Connection details for RDP */ - rdp?: ConsoleDetailPropType; - - /** Callback function. Generate content of .vv file. - * Parameters: ({ _console, type }) => ({ - * content, // required string value - * mimeType, // optional, default application/x-virt-viewer - * fileName // optional, default: console.vv - * }) - */ - onGenerate?: onGenerateFunctionType; - /** Callback function. Perform file download. - * Default implementation is usually good enough, but i.e. in case of environment with tight - * content security policy set, this might be required. - * - * Examples for alternative file-download implementations: - * - use of iframe - * - use of http-server - * - * Parameters: (fileName, content, mimeType) => {} - */ - onDownload?: onDownloadFunctionType; - - textConnectWithRemoteViewer?: string; - textMoreInfo?: string; - textMoreInfoContent?: string | React.ReactNode; - textConnectWithRDP?: string; - textMoreRDPInfo?: string; - textMoreRDPInfoContent?: string | React.ReactNode; -} - -export const ConnectWithRemoteViewer: React.FunctionComponent = ({ - onGenerate = generateDescriptorFile, - onDownload = downloadFile, - spice = null, - vnc = null, - rdp = null, - textConnectWithRemoteViewer = 'Launch Remote Viewer', - textConnectWithRDP = 'Launch Remote Desktop', - textMoreInfo = 'Remote Viewer Details', - textMoreInfoContent = '', - textMoreRDPInfo = 'Remote Desktop Details', - textMoreRDPInfoContent = '' -}: ConnectWithRemoteViewerProps) => { - const [isExpandedDefault, setIsExpandedDefault] = React.useState(false); - const [isExpandedRDP, setIsExpandedRDP] = React.useState(false); - - const _console = spice || vnc; // strictly prefer spice over vnc - - const onClickVV = () => { - const type = spice ? SPICE_CONSOLE_TYPE : VNC_CONSOLE_TYPE; - if (_console) { - const vv = onGenerate(_console, type); - return onDownload(DEFAULT_VV_FILENAME, vv.content, vv.mimeType || DEFAULT_VV_MIMETYPE); - } - }; - - const onClickRDP = () => { - const rdpFile = onGenerate(rdp, RDP_CONSOLE_TYPE); - return onDownload(DEFAULT_RDP_FILENAME, rdpFile.content, rdpFile.mimeType || DEFAULT_RDP_MIMETYPE); - }; - - // RDP button is rendered only if the protocol is available - // If none of Spice or VNC is available, the .vv button is disabled (but rendered) - return ( -
    -
    - - {!!rdp && ( - - )} -
    - {!!_console && ( - setIsExpandedDefault(isExpanded)} - > - - - )} - {!!rdp && ( - setIsExpandedRDP(isExpanded)} - > - - - )} -
    - ); -}; -ConnectWithRemoteViewer.displayName = 'ConnectWithRemoteViewer'; diff --git a/packages/react-console/src/components/DesktopViewer/ConsoleDetailPropType.tsx b/packages/react-console/src/components/DesktopViewer/ConsoleDetailPropType.tsx deleted file mode 100644 index f4f73b52f0a..00000000000 --- a/packages/react-console/src/components/DesktopViewer/ConsoleDetailPropType.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export interface ConsoleDetailPropType { - address: string; - port: string | number; - tlsPort?: string | number; -} diff --git a/packages/react-console/src/components/DesktopViewer/DesktopViewer.tsx b/packages/react-console/src/components/DesktopViewer/DesktopViewer.tsx deleted file mode 100644 index 6db7b27e895..00000000000 --- a/packages/react-console/src/components/DesktopViewer/DesktopViewer.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from 'react'; - -import { css } from '@patternfly/react-styles'; -import { ManualConnection } from './ManualConnection'; -import { ConnectWithRemoteViewer, ConnectWithRemoteViewerProps } from './ConnectWithRemoteViewer'; -import { ConsoleDetailPropType } from './ConsoleDetailPropType'; - -import styles from '@patternfly/react-styles/css/components/Consoles/DesktopViewer'; -import '@patternfly/react-styles/css/components/Consoles/DesktopViewer.css'; - -export interface DesktopViewerProps extends ConnectWithRemoteViewerProps { - /** Custom content of more-info section */ - children?: React.ReactNode; - /** Connection details for Spice */ - spice?: ConsoleDetailPropType; - /** Connection details for VNC */ - vnc?: ConsoleDetailPropType; - /** Connection details for RDP */ - rdp?: ConsoleDetailPropType; - - textManualConnection?: string; - textNoProtocol?: string; - textConnectWith?: string; - - textAddress?: string; - textSpiceAddress?: string; - textVNCAddress?: string; - textSpicePort?: string; - textVNCPort?: string; - textSpiceTlsPort?: string; - textVNCTlsPort?: string; - textRDPPort?: string; - textRdpAddress?: string; - - textConnectWithRemoteViewer?: string; - textConnectWithRDP?: string; - /** Text that appears in the toggle */ - textMoreInfo?: string; - /** The information content appearing above the description list for guidelines to install virt-viewer */ - textMoreInfoContent?: string | React.ReactNode; - /** Text that appears in the toggle */ - textMoreRDPInfo?: string; - /** The information content appearing above the description list for guidelines to install virt-viewer */ - textMoreRDPInfoContent?: string | React.ReactNode; -} - -export const DesktopViewer: React.FunctionComponent = ({ - children = null, - spice = null, - vnc = null, - rdp = null, - ...props -}: DesktopViewerProps) => ( -
    - - {children} - - -
    -); -DesktopViewer.displayName = 'DesktopViewer'; diff --git a/packages/react-console/src/components/DesktopViewer/ManualConnection.tsx b/packages/react-console/src/components/DesktopViewer/ManualConnection.tsx deleted file mode 100644 index a65a59915f3..00000000000 --- a/packages/react-console/src/components/DesktopViewer/ManualConnection.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React from 'react'; - -import { ConsoleDetailPropType } from './ConsoleDetailPropType'; -import { - DescriptionList, - DescriptionListGroup, - DescriptionListTerm, - DescriptionListDescription, - Title -} from '@patternfly/react-core'; - -export interface DetailProps extends React.HTMLProps { - title?: string; - value: string | number; -} -const Detail: React.FunctionComponent = ({ title, value }: DetailProps) => ( - - {title} - {value} - -); - -export interface ManualConnectionProps extends React.HTMLProps { - spice?: ConsoleDetailPropType; - vnc?: ConsoleDetailPropType; - rdp?: ConsoleDetailPropType; - - textManualConnection: string; - textNoProtocol: string; - textConnectWith: string; - - textAddress: string; - textSpiceAddress: string; - textVNCAddress: string; - textSpicePort: string; - textVNCPort: string; - textSpiceTlsPort: string; - textVNCTlsPort: string; - textRDPPort: string; - textRdpAddress: string; -} -export const ManualConnection: React.FunctionComponent = ({ - spice = null, - vnc = null, - rdp = null, - textManualConnection = 'Manual Connection', - textNoProtocol = 'No connection available.', - textConnectWith = 'Connect with any viewer application for following protocols', - textAddress = 'Address', - textSpiceAddress = 'SPICE Address', - textVNCAddress = 'VNC Address', - textSpicePort = 'SPICE Port', - textVNCPort = 'VNC Port', - textSpiceTlsPort = 'SPICE TLS Port', - textVNCTlsPort = 'VNC TLS Port', - textRDPPort = 'RDP Port', - textRdpAddress = 'RDP Address' -}: ManualConnectionProps) => { - const msg = spice || vnc ? textConnectWith : textNoProtocol; - const address = spice && vnc && spice.address === vnc.address && spice.address; - const rdpAddress = rdp && rdp.address !== address ? rdp.address : null; - - return ( -
    - - {textManualConnection} - -

    {msg}

    - - {address && } - {!address && spice && } - {rdpAddress && } - {spice && spice.port && } - {spice && spice.tlsPort && } - {!address && vnc && } - {vnc && vnc.port && } - {vnc && vnc.tlsPort && } - {rdp && rdp.port && } - -
    - ); -}; -ManualConnection.displayName = 'ManualConnection'; diff --git a/packages/react-console/src/components/DesktopViewer/MoreInformationDefaultContent.tsx b/packages/react-console/src/components/DesktopViewer/MoreInformationDefaultContent.tsx deleted file mode 100644 index 02db247cb68..00000000000 --- a/packages/react-console/src/components/DesktopViewer/MoreInformationDefaultContent.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; - -import { MoreInformationInstallVariant } from './MoreInformationInstallVariant'; -import { DescriptionList } from '@patternfly/react-core'; - -export interface MoreInformationDefaultContentProps { - textMoreInfoContent?: string | React.ReactNode; -} -export const MoreInformationDefaultContent: React.FunctionComponent = ({ - textMoreInfoContent = ( - <> -

    - Clicking "Launch Remote Viewer" will download a .vv file and launch Remote Viewer -

    -

    - Remote Viewer is available for most operating systems. To install it, search for it in GNOME Software or - run the following: -

    - - ) -}: MoreInformationDefaultContentProps) => ( - <> - {textMoreInfoContent} - - - - - -
    - Download the MSI from{' '} - - virt-manager.org - -
    -
    -
    - -); -MoreInformationDefaultContent.displayName = 'MoreInformationDefaultContent'; diff --git a/packages/react-console/src/components/DesktopViewer/MoreInformationDefaultRDPContent.tsx b/packages/react-console/src/components/DesktopViewer/MoreInformationDefaultRDPContent.tsx deleted file mode 100644 index 931743c235d..00000000000 --- a/packages/react-console/src/components/DesktopViewer/MoreInformationDefaultRDPContent.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -export interface MoreInformationDefaultRDPContentProps { - textMoreRDPInfoContent?: string | React.ReactNode; -} -export const MoreInformationDefaultRDPContent: React.FunctionComponent = ({ - textMoreRDPInfoContent = ( - <> -

    - Clicking "Launch Remote Desktop" will download an .rdp file and launch Remote Desktop Viewer. -

    -

    - Since the RDP is native Windows protocol, the best experience is achieved when used on Windows-based desktop. -

    -

    - For other operating systems, the Remote Viewer is recommended. If RDP needs to be accessed anyway, the{' '} - Remmina client is available. -

    - - ) -}: MoreInformationDefaultRDPContentProps) => <>{textMoreRDPInfoContent}; -MoreInformationDefaultRDPContent.displayName = 'MoreInformationDefaultRDPContent'; diff --git a/packages/react-console/src/components/DesktopViewer/MoreInformationInstallVariant.tsx b/packages/react-console/src/components/DesktopViewer/MoreInformationInstallVariant.tsx deleted file mode 100644 index 4ca3c296884..00000000000 --- a/packages/react-console/src/components/DesktopViewer/MoreInformationInstallVariant.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; - -import { DescriptionListTerm, DescriptionListGroup, DescriptionListDescription } from '@patternfly/react-core'; - -export interface MoreInformationInstallVariantProps { - children?: React.ReactNode; - os: string; - content?: string | React.ReactNode; -} - -export const MoreInformationInstallVariant: React.FunctionComponent = ({ - os = '', - content = null as string | React.ReactNode, - children = null -}: MoreInformationInstallVariantProps) => ( - - {os} - {content || children} - -); -MoreInformationInstallVariant.displayName = 'MoreInformationInstallVariant'; diff --git a/packages/react-console/src/components/DesktopViewer/__tests__/DesktopViewer.test.tsx b/packages/react-console/src/components/DesktopViewer/__tests__/DesktopViewer.test.tsx deleted file mode 100644 index 3066fc41e86..00000000000 --- a/packages/react-console/src/components/DesktopViewer/__tests__/DesktopViewer.test.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react'; -import { render, mount } from 'enzyme'; - -import { DesktopViewer } from '../DesktopViewer'; -import { MoreInformationDefaultContent } from '../MoreInformationDefaultContent'; -import { generateDescriptorFile } from '../consoleDescriptorGenerator'; -import { constants } from '../../common/constants'; - -const { SPICE_CONSOLE_TYPE, RDP_CONSOLE_TYPE, DEFAULT_RDP_PORT } = constants; - -const spice = { - address: 'my.host.com', - port: 5900, - tlsPort: '5901' -}; -const vnc = { - address: 'my.host.com', - port: 5902, - tlsPort: '5903' -}; - -const rdp = { - address: 'my.host.com', - port: DEFAULT_RDP_PORT -}; - -const rdp2 = { - address: 'my.differenthost.com', - port: 1234 -}; - -test('DesktopViewer empty', () => { - const wrapper = render(); - expect(wrapper).toMatchSnapshot(); -}); - -test('DesktopViewer with Spice and VNC', () => { - const wrapper = render(); - expect(wrapper).toMatchSnapshot(); -}); - -test('DesktopViewer with Spice, VNC and RDP', () => { - const wrapper = render(); - expect(wrapper).toMatchSnapshot(); -}); - -test('DesktopViewer with Spice, VNC and RDP (different hostname)', () => { - const wrapper = render(); - expect(wrapper).toMatchSnapshot(); -}); - -test('DesktopViewer launch button', () => { - const onDownload = jest.fn(); - const onGenerate = jest.fn().mockReturnValue({ content: 'Foo' }); - const wrapper = mount(); - const launchButton = wrapper.find('button.pf-c-console__remote-viewer-launch-vv'); - expect(launchButton).toHaveLength(1); - launchButton.simulate('click'); - expect(onGenerate).toHaveBeenCalledTimes(1); - expect(onDownload).toHaveBeenCalledTimes(1); -}); - -test('DesktopViewer RDP launch button', () => { - const onDownload = jest.fn(); - const onGenerate = jest.fn().mockReturnValue({ content: 'Foo' }); - const wrapper = mount(); - const launchButton = wrapper.find('button.pf-c-console__remote-viewer-launch-rdp'); - expect(launchButton).toHaveLength(1); - launchButton.simulate('click'); - expect(onGenerate).toHaveBeenCalledTimes(1); - expect(onDownload).toHaveBeenCalledTimes(1); -}); - -test('DesktopViewer with custom more-info content', () => { - const wrapper = mount( - -

    My more-info content

    -
    - ); - expect(wrapper).toMatchSnapshot(); - expect(wrapper.find('#custom-more-info')).toHaveLength(0); - const linkMoreInfo = wrapper.find('.pf-c-expandable-section__toggle'); - expect(linkMoreInfo).toHaveLength(1); - linkMoreInfo.simulate('click'); - expect(wrapper.find('.pf-c-expandable-section__content')).toHaveLength(1); -}); - -test('default MoreInformationContent', () => { - const wrapper = render(); - expect(wrapper).toMatchSnapshot(); -}); - -test('default implementation of generateVVFile()', () => { - const output = generateDescriptorFile(spice, SPICE_CONSOLE_TYPE); - expect(output.mimeType).toMatch('application/x-virt-viewer'); - expect(output.content).toMatch( - '[virt-viewer]\ntype=spice\nhost=my.host.com\nport=5900\ndelete-this-file=1\nfullscreen=0\n' - ); -}); - -test('default implementation of generateRDPFile()', () => { - const output = generateDescriptorFile(rdp, RDP_CONSOLE_TYPE); - expect(output.mimeType).toMatch('application/rdp'); - expect(output.content).toEqual(expect.stringContaining('full address:s:my.host.com:3389\n')); // the rest is a constant so far -}); diff --git a/packages/react-console/src/components/DesktopViewer/__tests__/__snapshots__/DesktopViewer.test.tsx.snap b/packages/react-console/src/components/DesktopViewer/__tests__/__snapshots__/DesktopViewer.test.tsx.snap deleted file mode 100644 index 31017e0e34e..00000000000 --- a/packages/react-console/src/components/DesktopViewer/__tests__/__snapshots__/DesktopViewer.test.tsx.snap +++ /dev/null @@ -1,1707 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DesktopViewer empty 1`] = ` -
    -
    -
    - -
    -
    -
    -

    - Manual Connection -

    -

    - No connection available. -

    -
    -
    -
    -`; - -exports[`DesktopViewer with Spice and VNC 1`] = ` -
    -
    -
    - -
    -
    - - -
    -
    -
    -

    - Manual Connection -

    -

    - Connect with any viewer application for following protocols -

    -
    -
    -
    - - Address - -
    -
    -
    - my.host.com -
    -
    -
    -
    -
    - - SPICE Port - -
    -
    -
    - 5900 -
    -
    -
    -
    -
    - - SPICE TLS Port - -
    -
    -
    - 5901 -
    -
    -
    -
    -
    - - VNC Port - -
    -
    -
    - 5902 -
    -
    -
    -
    -
    - - VNC TLS Port - -
    -
    -
    - 5903 -
    -
    -
    -
    -
    -
    -`; - -exports[`DesktopViewer with Spice, VNC and RDP (different hostname) 1`] = ` -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -

    - Manual Connection -

    -

    - Connect with any viewer application for following protocols -

    -
    -
    -
    - - Address - -
    -
    -
    - my.host.com -
    -
    -
    -
    -
    - - RDP Address - -
    -
    -
    - my.differenthost.com -
    -
    -
    -
    -
    - - SPICE Port - -
    -
    -
    - 5900 -
    -
    -
    -
    -
    - - SPICE TLS Port - -
    -
    -
    - 5901 -
    -
    -
    -
    -
    - - VNC Port - -
    -
    -
    - 5902 -
    -
    -
    -
    -
    - - VNC TLS Port - -
    -
    -
    - 5903 -
    -
    -
    -
    -
    - - RDP Port - -
    -
    -
    - 1234 -
    -
    -
    -
    -
    -
    -`; - -exports[`DesktopViewer with Spice, VNC and RDP 1`] = ` -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -

    - Manual Connection -

    -

    - Connect with any viewer application for following protocols -

    -
    -
    -
    - - Address - -
    -
    -
    - my.host.com -
    -
    -
    -
    -
    - - SPICE Port - -
    -
    -
    - 5900 -
    -
    -
    -
    -
    - - SPICE TLS Port - -
    -
    -
    - 5901 -
    -
    -
    -
    -
    - - VNC Port - -
    -
    -
    - 5902 -
    -
    -
    -
    -
    - - VNC TLS Port - -
    -
    -
    - 5903 -
    -
    -
    -
    -
    - - RDP Port - -
    -
    -
    - 3389 -
    -
    -
    -
    -
    -
    -`; - -exports[`DesktopViewer with custom more-info content 1`] = ` - -
    - -
    -
    - - - -
    - -
    - - -
    -
    -
    -
    - -
    - - <h2 - className="pf-c-title pf-m-3xl" - data-ouia-component-id="OUIA-Generated-Title-7" - data-ouia-component-type="PF4/Title" - data-ouia-safe={true} - > - Manual Connection - </h2> - -

    - Connect with any viewer application for following protocols -

    - -
    - - -
    - -
    - - Address - -
    -
    - -
    -
    - my.host.com -
    -
    -
    -
    -
    -
    - - -
    - -
    - - SPICE Port - -
    -
    - -
    -
    - 5900 -
    -
    -
    -
    -
    -
    - - -
    - -
    - - SPICE TLS Port - -
    -
    - -
    -
    - 5901 -
    -
    -
    -
    -
    -
    - - -
    - -
    - - VNC Port - -
    -
    - -
    -
    - 5902 -
    -
    -
    -
    -
    -
    - - -
    - -
    - - VNC TLS Port - -
    -
    - -
    -
    - 5903 -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`default MoreInformationContent 1`] = ` -Array [ -

    - Clicking "Launch Remote Viewer" will download a .vv file and launch - - Remote Viewer - -

    , -

    - - Remote Viewer - - is available for most operating systems. To install it, search for it in GNOME Software or run the following: -

    , -
    -
    -
    - - RHEL, CentOS - -
    -
    -
    - sudo yum install virt-viewer -
    -
    -
    -
    -
    - - Fedora - -
    -
    -
    - sudo dnf install virt-viewer -
    -
    -
    -
    -
    - - Ubuntu, Debian - -
    -
    -
    - sudo apt-get install virt-viewer -
    -
    -
    -
    -
    - - Windows - -
    -
    -
    -
    - Download the MSI from - - virt-manager.org - -
    -
    -
    -
    -
    , -] -`; diff --git a/packages/react-console/src/components/DesktopViewer/consoleDescriptorGenerator.tsx b/packages/react-console/src/components/DesktopViewer/consoleDescriptorGenerator.tsx deleted file mode 100644 index 3f626ac4414..00000000000 --- a/packages/react-console/src/components/DesktopViewer/consoleDescriptorGenerator.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { saveAs } from 'file-saver'; - -import { ConsoleDetailPropType } from './ConsoleDetailPropType'; -import { constants } from '../common/constants'; - -const { - VNC_CONSOLE_TYPE, - SPICE_CONSOLE_TYPE, - RDP_CONSOLE_TYPE, - DEFAULT_VV_MIMETYPE, - DEFAULT_RDP_MIMETYPE, - DEFAULT_RDP_PORT -} = constants; - -export type onDownloadFunctionType = (fileName: string, content: string, mimeType: string) => void; - -/** - * @param {string} fileName Default vv filename - * @param {string} content Content of the file - * @param {string} mimeType Defaylt vv mimeType - */ -export function downloadFile(fileName: string, content: string, mimeType: string) { - const blob = new Blob([content], { type: mimeType }); - saveAs(blob, fileName); -} - -/** - * @param {string} _console Object describing the console file content - * @param {string} type VNC_CONSOLE_TYPE | SPICE_CONSOLE_TYPE - */ -function generateVVFile(_console: ConsoleDetailPropType, type: string): { content: string; mimeType: string } { - const TYPES = { - [VNC_CONSOLE_TYPE]: 'vnc', - [SPICE_CONSOLE_TYPE]: 'spice' - }; - - const content = - '[virt-viewer]\n' + - `type=${TYPES[type] || type}\n` + // vnc or spice - `host=${_console.address}\n` + - `port=${_console.port}\n` + - 'delete-this-file=1\n' + - 'fullscreen=0\n'; - - return { - content, - mimeType: DEFAULT_VV_MIMETYPE - }; -} - -/** - * @param {string} _console Object describing the console file content - */ -function generateRDPFile(_console: ConsoleDetailPropType): { content: string; mimeType: string } { - const port = typeof _console.port !== 'undefined' && _console.port !== null ? _console.port : DEFAULT_RDP_PORT; - const content = [ - `full address:s:${_console.address}:${port}`, - '\nusername:s:Administrator', - '\nscreen mode id:i:2', // set 2 for full screen - '\nprompt for credentials:i:1', - '\ndesktopwidth:i:0', - '\ndesktopheight:i:0', - '\nauthentication level:i:2', - '\nredirectclipboard:i:1', - '\nsession bpp:i:32', - '\ncompression:i:1', - '\nkeyboardhook:i:2', - '\naudiocapturemode:i:0', - '\nvideoplaybackmode:i:1', - '\nconnection type:i:2', - '\ndisplayconnectionbar:i:1', - '\ndisable wallpaper:i:1', - '\nallow font smoothing:i:1', - '\nallow desktop composition:i:0', - '\ndisable full window drag:i:1', - '\ndisable menu anims:i:1', - '\ndisable themes:i:0', - '\ndisable cursor setting:i:0', - '\nbitmapcachepersistenable:i:1', - '\naudiomode:i:0', - '\nredirectcomports:i:0', - '\nredirectposdevices:i:0', - '\nredirectdirectx:i:1', - '\nautoreconnection enabled:i:1', - '\nnegotiate security layer:i:1', - '\nremoteapplicationmode:i:0', - '\nalternate shell:s:', - '\nshell working directory:s:', - '\ngatewayhostname:s:', - '\ngatewayusagemethod:i:4', - '\ngatewaycredentialssource:i:4', - '\ngatewayprofileusagemethod:i:0', - '\npromptcredentialonce:i:1', - '\nuse redirection server name:i:0', - '\n' - ].join(''); - - return { - content, - mimeType: DEFAULT_RDP_MIMETYPE - }; -} - -export type onGenerateFunctionType = ( - _console: ConsoleDetailPropType, - type: string -) => { content: string; mimeType: string }; - -/** - * @param {string} _console Object describing the console file content - * @param {string} type VNC_CONSOLE_TYPE | SPICE_CONSOLE_TYPE - */ -export function generateDescriptorFile( - _console: ConsoleDetailPropType, - type: string -): { content: string; mimeType: string } { - return type === RDP_CONSOLE_TYPE ? generateRDPFile(_console) : generateVVFile(_console, type); -} diff --git a/packages/react-console/src/components/DesktopViewer/examples/DesktopViewer.md b/packages/react-console/src/components/DesktopViewer/examples/DesktopViewer.md deleted file mode 100644 index 40152837e7b..00000000000 --- a/packages/react-console/src/components/DesktopViewer/examples/DesktopViewer.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: DesktopViewer -section: consoles -propComponents: ['DesktopViewer'] -ouia: false -beta: true ---- -### Note -DesktopViewer lives in its own package at [`@patternfly/react-console`](https://www.npmjs.com/package/@patternfly/react-console) - -import { DesktopViewer } from '@patternfly/react-console'; - -## Examples - -### Basic Usage -```js -import React from 'react'; -import { DesktopViewer } from '@patternfly/react-console'; - - -``` diff --git a/packages/react-console/src/components/DesktopViewer/index.ts b/packages/react-console/src/components/DesktopViewer/index.ts deleted file mode 100644 index 0c6fb7d5ee0..00000000000 --- a/packages/react-console/src/components/DesktopViewer/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './DesktopViewer'; -export * from './MoreInformationDefaultContent'; -export * from './MoreInformationInstallVariant'; diff --git a/packages/react-console/src/components/SerialConsole/SerialConsole.tsx b/packages/react-console/src/components/SerialConsole/SerialConsole.tsx deleted file mode 100644 index 8a755e380fb..00000000000 --- a/packages/react-console/src/components/SerialConsole/SerialConsole.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import React from 'react'; - -import { css } from '@patternfly/react-styles'; -import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, Spinner } from '@patternfly/react-core'; - -import { XTerm, XTermProps } from './XTerm'; -import { SerialConsoleActions } from './SerialConsoleActions'; - -import { constants } from '../common/constants'; - -import styles from '@patternfly/react-styles/css/components/Consoles/SerialConsole'; -import '@patternfly/react-styles/css/components/Consoles/xterm.css'; -import '@patternfly/react-styles/css/components/Consoles/SerialConsole.css'; - -const { CONNECTED, DISCONNECTED, LOADING } = constants; - -export interface SerialConsoleProps extends XTermProps { - /** Initiate connection to backend. In other words, the calling components manages connection state. */ - onConnect: () => void; - /** Close connection to backend */ - onDisconnect: () => void; - /** Terminal produced data, like key-press */ - onData: (e: string) => void; - /** Terminal title has been changed */ - onTitleChanged?: () => void; - /** Connection status; a value from [''connected'; 'disconnected'; 'loading']. Default is 'loading' for a not matching value. */ - /** The number of columns to resize to */ - cols?: number; - /** The number of rows to resize to */ - rows?: number; - fontFamily?: string; - fontSize?: number; - status?: string; - /** Text content rendered inside the Connect button */ - textConnect?: string; - /** Text content rendered inside the Disconnect button */ - textDisconnect?: string; - /** Text content rendered inside the Reset button */ - textReset?: string; - /* Text content rendered inside the EmptyState for when console is disconnnected */ - textDisconnected?: string; - /* Text content rendered inside the EmptyState for when console is loading */ - textLoading?: string; - /** A reference object to attach to the SerialConsole. */ - innerRef?: React.RefObject; -} - -const SerialConsoleBase: React.FunctionComponent = ({ - onConnect, - onDisconnect, - onTitleChanged = () => {}, - onData, - cols, - rows, - fontFamily, - fontSize, - status = 'loading', - textConnect = 'Connect', - textDisconnect, - textReset, - textDisconnected = 'Click Connect to open serial console.', - textLoading = 'Loading ...', - innerRef -}) => { - React.useEffect(() => { - onConnect(); - return () => { - onDisconnect(); - }; - }, []); - - const onConnectClick = () => { - onConnect(); - focusTerminal(); - }; - - const onDisconnectClick = () => { - onDisconnect(); - focusTerminal(); - }; - - const onResetClick = () => { - onDisconnect(); - onConnect(); - focusTerminal(); - }; - - const focusTerminal = () => { - innerRef && innerRef.current && innerRef.current.focusTerminal(); - }; - - let terminal; - switch (status) { - case CONNECTED: - terminal = ( - - ); - break; - case DISCONNECTED: - terminal = ( - - {textDisconnected} - - - ); - break; - case LOADING: - default: - terminal = ( - - - {textLoading} - - ); - break; - } - - return ( - <> - {status !== DISCONNECTED && ( - - )} -
    {terminal}
    - - ); -}; -SerialConsoleBase.displayName = 'SerialConsoleBase'; -export const SerialConsole = React.forwardRef((props: SerialConsoleProps, ref: React.Ref) => ( - } {...props} /> -)); -SerialConsole.displayName = 'SerialConsole'; diff --git a/packages/react-console/src/components/SerialConsole/SerialConsoleActions.tsx b/packages/react-console/src/components/SerialConsole/SerialConsoleActions.tsx deleted file mode 100644 index 770f5571d25..00000000000 --- a/packages/react-console/src/components/SerialConsole/SerialConsoleActions.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import { css } from '@patternfly/react-styles'; -import { Button } from '@patternfly/react-core'; - -import styles from '@patternfly/react-styles/css/components/Consoles/SerialConsole'; - -export interface SerialConsoleActionsProps extends React.HTMLProps { - onDisconnect: () => void; - onReset: () => void; - textDisconnect?: string; - textReset?: string; -} - -export const SerialConsoleActions: React.FunctionComponent = ({ - textDisconnect = 'Disconnect', - textReset = 'Reset', - ...props -}: SerialConsoleActionsProps) => ( -
    - - -
    -); -SerialConsoleActions.displayName = 'SerialConsoleActions'; diff --git a/packages/react-console/src/components/SerialConsole/XTerm.tsx b/packages/react-console/src/components/SerialConsole/XTerm.tsx deleted file mode 100644 index 12d8a44b4fe..00000000000 --- a/packages/react-console/src/components/SerialConsole/XTerm.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import React, { useImperativeHandle } from 'react'; - -import { Terminal } from 'xterm'; -import { FitAddon } from 'xterm-addon-fit'; - -import { debounce, canUseDOM } from '@patternfly/react-core'; - -export interface XTermProps { - /** The number of columns to resize to */ - cols?: number; - /** The number of rows to resize to */ - rows?: number; - fontFamily?: string; - fontSize?: number; - /** Terminal title has been changed. */ - onTitleChanged?: (title: string) => void; - /** Data to be sent from terminal to backend; (data) => {} */ - onData?: (e: string) => void; - /** A reference object to attach to the xterm */ - innerRef?: React.RefObject; -} - -export const XTerm: React.FunctionComponent = ({ - cols = 80, - rows = 25, - fontFamily, - fontSize, - onTitleChanged, - onData, - innerRef -}) => { - let terminal: Terminal; - const ref = React.useRef(); - - useImperativeHandle(innerRef, () => ({ - focusTerminal() { - if (terminal) { - terminal.focus(); - } - }, - /** - * Backend sent data. - * - * @param {string} data String content to be writen into the terminal - */ - onDataReceived: (data: string) => { - if (terminal) { - terminal.write(data); - } - }, - /** - * Backend closed connection. - * - * @param {string} reason String error to be written into the terminal - */ - onConnectionClosed: (reason: string) => { - if (terminal) { - terminal.write(`\x1b[31m${reason || 'disconnected'}\x1b[m\r\n`); - terminal.refresh(terminal.rows, terminal.rows); // start to end row - } - } - })); - - React.useEffect(() => { - const fitAddon = new FitAddon(); - terminal = new Terminal({ - cols, - rows, - cursorBlink: true, - fontFamily, - fontSize, - screenReaderMode: true - }); - - const onWindowResize = () => { - const geometry = fitAddon.proposeDimensions(); - if (geometry) { - terminal.resize(geometry.rows, geometry.cols); - } - }; - - if (onData) { - terminal.onData(onData); - } - - if (onTitleChanged) { - terminal.onTitleChange(onTitleChanged); - } - - terminal.loadAddon(fitAddon); - - terminal.open(ref.current); - - const resizeListener = debounce(onWindowResize, 100); - - if (!rows) { - if (canUseDOM) { - window.addEventListener('resize', resizeListener); - } - onWindowResize(); - } - terminal.focus(); - - return () => { - terminal.dispose(); - if (canUseDOM) { - window.removeEventListener('resize', resizeListener); - } - onFocusOut(); - }; - }, []); - - const onBeforeUnload = (event: any) => { - // Firefox requires this when the page is in an iframe - event.preventDefault(); - - // see "an almost cross-browser solution" at - // https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload - event.returnValue = ''; - return ''; - }; - - const onFocusIn = () => { - window.addEventListener('beforeunload', onBeforeUnload); - }; - - const onFocusOut = () => { - window.removeEventListener('beforeunload', onBeforeUnload); - }; - - // ensure react never reuses this div by keying it with the terminal widget - // Workaround for xtermjs/xterm.js#3172 - return
    ; -}; -XTerm.displayName = 'XTerm'; diff --git a/packages/react-console/src/components/SerialConsole/__tests__/SerialConsole.test.tsx b/packages/react-console/src/components/SerialConsole/__tests__/SerialConsole.test.tsx deleted file mode 100644 index 2af5f23a354..00000000000 --- a/packages/react-console/src/components/SerialConsole/__tests__/SerialConsole.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import { shallow, render } from 'enzyme'; -import { SerialConsole } from '../SerialConsole'; -import { constants } from '../../common/constants'; - -const { CONNECTED, DISCONNECTED, LOADING } = constants; - -test('SerialConsole in the LOADING state', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); - -test('SerialConsole in the DISCONNECTED state', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); - -const connectedState = ( - -); - -test('SerialConsole in the CONNECTED state', () => { - const view = shallow(connectedState); - expect(view).toMatchSnapshot(); -}); - -test('Render SerialConsole in the CONNECTED state', () => { - const view = render(connectedState); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-console/src/components/SerialConsole/__tests__/SerialConsoleActions.test.tsx b/packages/react-console/src/components/SerialConsole/__tests__/SerialConsoleActions.test.tsx deleted file mode 100644 index 15a99dbb871..00000000000 --- a/packages/react-console/src/components/SerialConsole/__tests__/SerialConsoleActions.test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import { SerialConsoleActions } from '../SerialConsoleActions'; - -test('placeholder render test', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('Render SerialConsoleActions', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); - -test('Render SerialConsoleActions with custom texts', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-console/src/components/SerialConsole/__tests__/XTerm.test.tsx b/packages/react-console/src/components/SerialConsole/__tests__/XTerm.test.tsx deleted file mode 100644 index 308e226416c..00000000000 --- a/packages/react-console/src/components/SerialConsole/__tests__/XTerm.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { render } from 'enzyme'; -import { XTerm } from '../XTerm'; - -test('Render empty XTerm component', () => { - const view = render(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/SerialConsole.test.tsx.snap b/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/SerialConsole.test.tsx.snap deleted file mode 100644 index 1d646d7bbf2..00000000000 --- a/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/SerialConsole.test.tsx.snap +++ /dev/null @@ -1,75 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Render SerialConsole in the CONNECTED state 1`] = ` -Array [ -
    - - -
    , -
    -
    -
    , -] -`; - -exports[`SerialConsole in the CONNECTED state 1`] = ` - -`; - -exports[`SerialConsole in the DISCONNECTED state 1`] = ` - -`; - -exports[`SerialConsole in the LOADING state 1`] = ` - -`; diff --git a/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/SerialConsoleActions.test.tsx.snap b/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/SerialConsoleActions.test.tsx.snap deleted file mode 100644 index ba0df2f17b0..00000000000 --- a/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/SerialConsoleActions.test.tsx.snap +++ /dev/null @@ -1,56 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Render SerialConsoleActions 1`] = ` -
    - - -
    -`; - -exports[`Render SerialConsoleActions with custom texts 1`] = ` -
    - - -
    -`; - -exports[`placeholder render test 1`] = ` -
    - - -
    -`; diff --git a/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/XTerm.test.tsx.snap b/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/XTerm.test.tsx.snap deleted file mode 100644 index 8c48cc9b015..00000000000 --- a/packages/react-console/src/components/SerialConsole/__tests__/__snapshots__/XTerm.test.tsx.snap +++ /dev/null @@ -1,8 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Render empty XTerm component 1`] = ` -
    -`; diff --git a/packages/react-console/src/components/SerialConsole/index.ts b/packages/react-console/src/components/SerialConsole/index.ts deleted file mode 100644 index 3c4f5f4b56b..00000000000 --- a/packages/react-console/src/components/SerialConsole/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './SerialConsole'; diff --git a/packages/react-console/src/components/SpiceConsole/SpiceActions.tsx b/packages/react-console/src/components/SpiceConsole/SpiceActions.tsx deleted file mode 100644 index e400e0a7b4d..00000000000 --- a/packages/react-console/src/components/SpiceConsole/SpiceActions.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Dropdown, DropdownItem, DropdownToggle } from '@patternfly/react-core'; - -export interface SpiceActionsProps extends React.HTMLProps { - /** Callback for when Ctrl+Alt+Delete item is selected */ - onCtrlAltDel?: () => void; - /** Text for the Dropdown Ctrl+Alt+Delety item */ - textCtrlAltDel?: string; - /** Text for the Dropdown toggle button */ - textSendShortcut?: string; -} -export const SpiceActions: React.FunctionComponent = ({ - textSendShortcut = 'Send Key', - textCtrlAltDel = 'Ctrl+Alt+Del', - onCtrlAltDel -}: SpiceActionsProps) => { - const [isOpen, setIsOpen] = React.useState(false); - - return ( - { - setIsOpen(!isOpen); - onCtrlAltDel(); - }} - isOpen={isOpen} - toggle={ - setIsOpen(isDropdownOpen)}>{textSendShortcut} - } - dropdownItems={[{textCtrlAltDel}]} - /> - ); -}; -SpiceActions.displayName = 'SpiceActions'; diff --git a/packages/react-console/src/components/SpiceConsole/SpiceConsole.tsx b/packages/react-console/src/components/SpiceConsole/SpiceConsole.tsx deleted file mode 100644 index 7fca64c050c..00000000000 --- a/packages/react-console/src/components/SpiceConsole/SpiceConsole.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import React from 'react'; -import { css } from '@patternfly/react-styles'; -import { SpiceMainConn, sendCtrlAltDel } from '@spice-project/spice-html5'; - -import { constants } from '../common/constants'; -import { SpiceActions } from './SpiceActions'; - -const { CONNECTED, CONNECTING, DISCONNECTED } = constants; - -export interface SpiceConsoleProps extends React.HTMLProps { - /** Children nodes */ - children?: React.ReactNode; - /** FQDN or IP to connect to */ - host?: string; - /** TCP Port */ - port?: string; - /** host:port/path */ - path?: string; - /** Enable use of TLS encryption on the SPICE server */ - encrypt?: boolean; - /** token */ - password?: string; - /** Additional classes added to the component */ - className?: string; - - /** Callback. Spice server disconnected. */ - onDisconnected?: (e: any) => void; - /** Initialization of Spice failed */ - onInitFailed?: (e: any) => void; - - textConnecting?: string; - textDisconnected?: string; - textSendShortcut?: string; - textCtrlAltDel?: string; -} - -export const SpiceConsole: React.FunctionComponent = ({ - children = null, - host = '', - port = '80', - path = '', - encrypt = false, - password, - className = '', - onDisconnected, - onInitFailed, - textConnecting = 'Connecting', - textDisconnected = 'Disconnected', - textSendShortcut, - textCtrlAltDel -}) => { - let spiceStaticComponent: React.ReactNode; - let sc: any; - const [status, setStatus] = React.useState(CONNECTING); - - React.useEffect(() => { - try { - const protocol = encrypt ? 'wss' : 'ws'; - const uri = `${protocol}://${host}:${port}/${path}`; - - sc = new SpiceMainConn({ - uri, - /* eslint-disable camelcase */ - screen_id: 'spice-screen', - password, - onerror: onSpiceError, - onsuccess: setStatus(CONNECTED) - }); - } catch (e) { - onInitFailed && onInitFailed(e); - disconnect(); - } - return () => disconnect(); - }, []); - - const disconnect = () => { - if (sc) { - sc.stop(); - sc = undefined; - } - }; - - const onCtrlAltDel = () => { - if (sc) { - sendCtrlAltDel(); - } - }; - - const onSpiceError = (e: any) => { - disconnect(); - setStatus(DISCONNECTED); - onDisconnected(e); - }; - - if (!spiceStaticComponent) { - // create just once - spiceStaticComponent =
    ; - } - - return ( -
    - {children} -
    - {status === CONNECTED && ( - - )} -
    -
    - {(status === DISCONNECTED || status === CONNECTING) && ( -
    {status === DISCONNECTED ? textDisconnected : textConnecting}
    - )} - {status} - {spiceStaticComponent} -
    -
    - ); -}; -SpiceConsole.displayName = 'SpiceConsole'; diff --git a/packages/react-console/src/components/SpiceConsole/index.ts b/packages/react-console/src/components/SpiceConsole/index.ts deleted file mode 100644 index 066cba6c4f0..00000000000 --- a/packages/react-console/src/components/SpiceConsole/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './SpiceConsole'; diff --git a/packages/react-console/src/components/VncConsole/VncActions.tsx b/packages/react-console/src/components/VncConsole/VncActions.tsx deleted file mode 100644 index 30c1d1de11a..00000000000 --- a/packages/react-console/src/components/VncConsole/VncActions.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import { css } from '@patternfly/react-styles'; -import { Dropdown, DropdownItem, DropdownToggle, Button, ButtonVariant } from '@patternfly/react-core'; - -import styles from '@patternfly/react-styles/css/components/Consoles/VncConsole'; - -export interface VncActionProps { - onDisconnect: (event: React.MouseEvent) => void; - onCtrlAltDel: () => void; - - textCtrlAltDel?: string; - textSendShortcut?: string; - textDisconnect?: string; - - /** VNC console additional action elements */ - additionalButtons?: React.ReactNode[]; -} -export const VncActions: React.FunctionComponent = ({ - textSendShortcut = 'Send Key', - textCtrlAltDel = 'Ctrl+Alt+Del', - textDisconnect = 'Disconnect', - onCtrlAltDel = undefined, - onDisconnect, - additionalButtons = [] -}) => { - const [isOpen, setIsOpen] = React.useState(false); - const toolbar = ( -
    - {additionalButtons} - setIsOpen(false)} - toggle={ - setIsOpen(!isOpen)}> - {textSendShortcut} - - } - isOpen={isOpen} - dropdownItems={[ - - {textCtrlAltDel} - - ]} - /> - -
    - ); - - return toolbar; -}; -VncActions.displayName = 'VncActions'; diff --git a/packages/react-console/src/components/VncConsole/VncConsole.tsx b/packages/react-console/src/components/VncConsole/VncConsole.tsx deleted file mode 100644 index 85f144008bc..00000000000 --- a/packages/react-console/src/components/VncConsole/VncConsole.tsx +++ /dev/null @@ -1,229 +0,0 @@ -import React from 'react'; - -import { css } from '@patternfly/react-styles'; -import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, Spinner } from '@patternfly/react-core'; - -import { initLogging } from '@novnc/novnc/core/util/logging'; -/** Has bad types. https://github.com/larryprice/novnc-core/issues/5 */ -import RFB from '@novnc/novnc/core/rfb'; - -import { VncActions } from './VncActions'; -import { constants } from '../common/constants'; - -import styles from '@patternfly/react-styles/css/components/Consoles/VncConsole'; -import '@patternfly/react-styles/css/components/Consoles/VncConsole.css'; - -const { CONNECTED, CONNECTING, DISCONNECTED } = constants; - -export interface VncConsoleProps extends React.HTMLProps { - /** Children nodes */ - children?: React.ReactNode; - - /** FQDN or IP to connect to */ - host: string; - /** TCP Port */ - port?: string; - /** host:port/path */ - path?: string; - encrypt?: boolean; - /** Is a boolean indicating if a request to resize the remote session should be sent whenever the container changes dimensions */ - resizeSession?: boolean; - /** Is a boolean indicating if the remote session should be scaled locally so it fits its container */ - scaleViewport?: boolean; - /** Is a boolean indicating if any events (e.g. key presses or mouse movement) should be prevented from being sent to the server */ - viewOnly?: boolean; - /** Is a boolean indicating if the remote server should be shared or if any other connected clients should be disconnected */ - shared?: boolean; - /** An Object specifying the credentials to provide to the server when authenticating - * { username: '' password: '' target: ''} - */ - credentials?: object; - /** A DOMString specifying the ID to provide to any VNC repeater encountered */ - repeaterID?: string; - /** log-level for noVNC */ - vncLogging?: 'error' | 'warn' | 'none' | 'debug' | 'info'; - consoleContainerId?: string; - additionalButtons?: React.ReactNode[]; - - /** Callback. VNC server disconnected. */ - onDisconnected?: (e: any) => void; - /** Initialization of RFB failed */ - onInitFailed?: (e: any) => void; - /** Handshake failed */ - onSecurityFailure?: (e: any) => void; - - /* Text content rendered inside the EmptyState in the "Connect' button for when console is disconnnected */ - textConnect?: string; - /* Text content rendered inside the EmptyState for when console is connecting */ - textConnecting?: string | React.ReactNode; - /* Text content rendered inside the EmptyState for when console is disconnnected */ - textDisconnected?: string; - /** Text content rendered inside the Disconnect button */ - textDisconnect?: string; - /** Text content rendered inside the button Send shortcut dropdown toggle */ - textSendShortcut?: string; - /** Text content rendered inside the Ctrl-Alt-Delete dropdown entry */ - textCtrlAltDel?: string; -} - -export const VncConsole: React.FunctionComponent = ({ - children, - host, - port = '80', - path = '', - encrypt = false, - resizeSession = true, - scaleViewport = false, - viewOnly = false, - shared = false, - credentials, - repeaterID = '', - vncLogging = 'warn', - consoleContainerId, - additionalButtons = [] as React.ReactNode[], - onDisconnected = () => {}, - onInitFailed, - onSecurityFailure, - textConnect = 'Connect', - textConnecting = 'Connecting', - textDisconnected = 'Click Connect to open the VNC console.', - textDisconnect = 'Disconnect', - textSendShortcut, - textCtrlAltDel -}) => { - const rfb = React.useRef(); - let novncStaticComponent: React.ReactNode; - let novncElem: HTMLDivElement; - - const [status, setStatus] = React.useState(CONNECTING); - - const addEventListeners = () => { - if (rfb.current) { - rfb.current?.addEventListener('connect', onConnected); - rfb.current?.addEventListener('disconnect', _onDisconnected); - rfb.current?.addEventListener('securityfailure', _onSecurityFailure); - } - }; - - const removeEventListeners = () => { - if (rfb.current) { - rfb.current.removeEventListener('connect', onConnected); - rfb.current.removeEventListener('disconnect', _onDisconnected); - rfb.current.removeEventListener('securityfailure', _onSecurityFailure); - } - }; - - const connect = () => { - const protocol = encrypt ? 'wss' : 'ws'; - const url = `${protocol}://${host}:${port}/${path}`; - - const options = { - repeaterID, - shared, - credentials - }; - rfb.current = new RFB(novncElem, url, options); - addEventListeners(); - rfb.current.viewOnly = viewOnly; - rfb.current.scaleViewport = scaleViewport; - rfb.current.resizeSession = resizeSession; - }; - - React.useEffect(() => { - initLogging(vncLogging); - try { - connect(); - } catch (e) { - onInitFailed && onInitFailed(e); - rfb.current = undefined; - } - - return () => { - disconnect(); - removeEventListeners(); - rfb.current = undefined; - }; - }, []); - - const disconnect = () => { - if (!rfb.current) { - return; - } - rfb.current.disconnect(); - }; - - const onConnected = () => { - setStatus(CONNECTED); - }; - - const _onDisconnected = (e: any) => { - setStatus(DISCONNECTED); - onDisconnected(e); - }; - - const _onSecurityFailure = (e: any) => { - setStatus(DISCONNECTED); - onSecurityFailure(e); - }; - - const onCtrlAltDel = () => { - if (rfb.current) { - rfb?.current?.sendCtrlAltDel(); - } - }; - - let rightContent; - let emptyState; - switch (status) { - case CONNECTED: - rightContent = ( - - ); - break; - case DISCONNECTED: - emptyState = ( - - {textDisconnected} - - - ); - break; - case CONNECTING: - default: - emptyState = ( - - - {textConnecting} - - ); - } - - if (!novncStaticComponent) { - novncStaticComponent =
    (novncElem = e)} />; - } - - return ( - <> - {rightContent} -
    - {children} - -
    - {emptyState} - {novncStaticComponent} -
    -
    -
    - - ); -}; -VncConsole.displayName = 'VncConsole'; diff --git a/packages/react-console/src/components/VncConsole/__tests__/VncConsole.test.tsx b/packages/react-console/src/components/VncConsole/__tests__/VncConsole.test.tsx deleted file mode 100644 index bb26ae5a622..00000000000 --- a/packages/react-console/src/components/VncConsole/__tests__/VncConsole.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -import React from 'react'; -import { shallow } from 'enzyme'; -import { VncConsole } from '../../VncConsole'; - -test('placeholder render test', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-console/src/components/VncConsole/__tests__/VncConsoleActions.test.tsx b/packages/react-console/src/components/VncConsole/__tests__/VncConsoleActions.test.tsx deleted file mode 100644 index e5bc3b4f624..00000000000 --- a/packages/react-console/src/components/VncConsole/__tests__/VncConsoleActions.test.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; -import { VncActions } from '../VncActions'; - -test('placeholder render test', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('VncActions renders correctly component hierarchy', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); - -test('VncActions renders correctly html', () => { - const view = shallow( - - ); - expect(view.html()).toMatchSnapshot(); -}); - -test('VncActions calls ctrl+alt+del action', () => { - const onCtrlAltDel = jest.fn(); - - const wrapper = mount( - - ); - - const button = wrapper.find('button.pf-c-dropdown__toggle'); - button.simulate('click'); - expect(wrapper.find('ul li')).toHaveLength(1); - wrapper - .find('ul li a') - .simulate('click'); - expect(onCtrlAltDel).toHaveBeenCalledTimes(1); -}); diff --git a/packages/react-console/src/components/VncConsole/__tests__/__snapshots__/VncConsole.test.tsx.snap b/packages/react-console/src/components/VncConsole/__tests__/__snapshots__/VncConsole.test.tsx.snap deleted file mode 100644 index e404ee0135c..00000000000 --- a/packages/react-console/src/components/VncConsole/__tests__/__snapshots__/VncConsole.test.tsx.snap +++ /dev/null @@ -1,22 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`placeholder render test 1`] = ` - -
    -
    - - - - Connecting - - -
    -
    -
    - -`; diff --git a/packages/react-console/src/components/VncConsole/__tests__/__snapshots__/VncConsoleActions.test.tsx.snap b/packages/react-console/src/components/VncConsole/__tests__/__snapshots__/VncConsoleActions.test.tsx.snap deleted file mode 100644 index 3e48965224e..00000000000 --- a/packages/react-console/src/components/VncConsole/__tests__/__snapshots__/VncConsoleActions.test.tsx.snap +++ /dev/null @@ -1,71 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`VncActions renders correctly component hierarchy 1`] = ` -
    - - foobar - , - ] - } - id="pf-c-console__send-shortcut" - isOpen={false} - onSelect={[Function]} - toggle={ - - My Send Shortcut description - - } - /> - -
    -`; - -exports[`VncActions renders correctly html 1`] = `"
    "`; - -exports[`placeholder render test 1`] = ` -
    - - Ctrl+Alt+Del - , - ] - } - id="pf-c-console__send-shortcut" - isOpen={false} - onSelect={[Function]} - toggle={ - - Send Key - - } - /> - -
    -`; diff --git a/packages/react-console/src/components/VncConsole/index.ts b/packages/react-console/src/components/VncConsole/index.ts deleted file mode 100644 index c0ce29914fe..00000000000 --- a/packages/react-console/src/components/VncConsole/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './VncConsole'; diff --git a/packages/react-console/src/components/common/constants.tsx b/packages/react-console/src/components/common/constants.tsx deleted file mode 100644 index f69b8059a9e..00000000000 --- a/packages/react-console/src/components/common/constants.tsx +++ /dev/null @@ -1,37 +0,0 @@ -const NONE_TYPE = '_none_'; -const SERIAL_CONSOLE_TYPE = 'SerialConsole'; -const SPICE_CONSOLE_TYPE = 'SpiceConsole'; -const VNC_CONSOLE_TYPE = 'VncConsole'; -const RDP_CONSOLE_TYPE = 'RdpConsole'; -const DESKTOP_VIEWER_CONSOLE_TYPE = 'DesktopViewer'; - -const CONNECTING = 'connecting'; -const CONNECTED = 'connected'; -const DISCONNECTED = 'disconnected'; -const LOADING = 'loading'; - -const DEFAULT_VV_FILENAME = 'console.vv'; -const DEFAULT_VV_MIMETYPE = 'application/x-virt-viewer'; -const DEFAULT_RDP_FILENAME = 'console.rdp'; -const DEFAULT_RDP_MIMETYPE = 'application/rdp'; -const DEFAULT_RDP_PORT = 3389; - -export const constants = { - NONE_TYPE, - SERIAL_CONSOLE_TYPE, - SPICE_CONSOLE_TYPE, - VNC_CONSOLE_TYPE, - RDP_CONSOLE_TYPE, - DESKTOP_VIEWER_CONSOLE_TYPE, - - CONNECTING, - CONNECTED, - DISCONNECTED, - LOADING, - - DEFAULT_VV_FILENAME, - DEFAULT_VV_MIMETYPE, - DEFAULT_RDP_FILENAME, - DEFAULT_RDP_MIMETYPE, - DEFAULT_RDP_PORT -}; diff --git a/packages/react-console/src/components/common/helpers.tsx b/packages/react-console/src/components/common/helpers.tsx deleted file mode 100644 index 113179a5610..00000000000 --- a/packages/react-console/src/components/common/helpers.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; - -export const child = (children: React.ReactNode, index: number) => { - const childrenArray = React.Children.toArray(children); - return (childrenArray && childrenArray.length > index && childrenArray[index]) || null; -}; diff --git a/packages/react-console/src/components/index.ts b/packages/react-console/src/components/index.ts deleted file mode 100644 index d9fefd8cdf2..00000000000 --- a/packages/react-console/src/components/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** Keep alphabetically sorted */ -export * from './AccessConsoles'; -export * from './DesktopViewer'; -export * from './SerialConsole'; -export * from './SpiceConsole'; -export * from './VncConsole'; -export * from './common/constants'; diff --git a/packages/react-console/src/declarations.d.ts b/packages/react-console/src/declarations.d.ts deleted file mode 100644 index e9eb931b709..00000000000 --- a/packages/react-console/src/declarations.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -declare module '@spice-project/spice-html5' { - export const SpiceMainConn: any; - export const sendCtrlAltDel: any; -} - -declare module '@novnc/novnc/core/rfb' { - class RFB { - constructor(target: any, url: any, options: any); - } - export = RFB; -} - -declare module '@novnc/novnc/core/util/logging' { - export const initLogging: any; -} diff --git a/packages/react-console/tsconfig.json b/packages/react-console/tsconfig.json deleted file mode 100644 index 30bec2faa4a..00000000000 --- a/packages/react-console/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "compilerOptions": { - "rootDir": "./src", - "outDir": "./dist/esm", - "tsBuildInfoFile": "dist/esm.tsbuildinfo" - }, - "include": [ - "./src/*", - "./src/**/*" - ] -} diff --git a/packages/react-core/.gitignore b/packages/react-core/.gitignore new file mode 100644 index 00000000000..77cfc55e590 --- /dev/null +++ b/packages/react-core/.gitignore @@ -0,0 +1,5 @@ +/next +/deprecated +/components +/layouts +/helpers \ No newline at end of file diff --git a/packages/react-core/.npmignore b/packages/react-core/.npmignore index dbe7561151c..2acd10b08d6 100644 --- a/packages/react-core/.npmignore +++ b/packages/react-core/.npmignore @@ -1,3 +1,3 @@ dist/*.tsbuildinfo tsconfig.* -rollup.config.js \ No newline at end of file +rollup.config.mjs diff --git a/packages/react-core/CHANGELOG.md b/packages/react-core/CHANGELOG.md index eb27463cacd..99453bbadc1 100644 --- a/packages/react-core/CHANGELOG.md +++ b/packages/react-core/CHANGELOG.md @@ -3,12876 +3,4178 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. -# 4.188.0 (2022-01-14) - - -### Features - -* **DescriptionList:** add option to fill columns first ([#6736](https://github.com/patternfly/patternfly-react/issues/6736)) ([c955c29](https://github.com/patternfly/patternfly-react/commit/c955c2917dbc4b85ce58fac4f93845c429186e1b)) - - +# [6.6.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.1-prerelease.0...@patternfly/react-core@6.6.0-prerelease.1) (2026-05-26) +### Bug Fixes +- updated to do 6.6.0 prereleases. ([#12434](https://github.com/patternfly/patternfly-react/issues/12434)) ([6e09ce8](https://github.com/patternfly/patternfly-react/commit/6e09ce8322ff13354991d901782231d437249aa6)) -## 4.187.2 (2022-01-14) +## [6.5.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0...@patternfly/react-core@6.5.1-prerelease.0) (2026-05-21) **Note:** Version bump only for package @patternfly/react-core +# 6.5.0 (2026-05-20) +### Reverts +- Revert "chore(release): releasing packages [ci skip]" ([7185856](https://github.com/patternfly/patternfly-react/commit/7185856d4985da5129bbabd6c460049e7048dd2a)) +# [6.5.0-prerelease.79](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.78...@patternfly/react-core@6.5.0-prerelease.79) (2026-05-19) -## 4.187.1 (2022-01-14) +### Features -**Note:** Version bump only for package @patternfly/react-core +- **ver:** bump core to .93 ([#12429](https://github.com/patternfly/patternfly-react/issues/12429)) ([bdbbf84](https://github.com/patternfly/patternfly-react/commit/bdbbf84d9b4bc6f4434b51d99ca5db0563841af8)) +# [6.5.0-prerelease.78](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.77...@patternfly/react-core@6.5.0-prerelease.78) (2026-05-14) +### Features +- **ver:** core bump ([#12427](https://github.com/patternfly/patternfly-react/issues/12427)) ([71b2433](https://github.com/patternfly/patternfly-react/commit/71b243388f761946db0043da8c288df1a1e9b70a)) +# [6.5.0-prerelease.77](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.76...@patternfly/react-core@6.5.0-prerelease.77) (2026-05-13) -# 4.187.0 (2022-01-12) +**Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.76](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.75...@patternfly/react-core@6.5.0-prerelease.76) (2026-05-12) ### Features -* **expandable-section:** added indented variation ([#6763](https://github.com/patternfly/patternfly-react/issues/6763)) ([703b922](https://github.com/patternfly/patternfly-react/commit/703b9224e43bedd5b37ec41d8f26f2939836d610)) - - +- **Compass:** remove background props, update structure ([#12408](https://github.com/patternfly/patternfly-react/issues/12408)) ([5564f73](https://github.com/patternfly/patternfly-react/commit/5564f730fb899c3f8968cbcc567cbded2def367e)) +# [6.5.0-prerelease.75](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.74...@patternfly/react-core@6.5.0-prerelease.75) (2026-05-12) +### Features -## 4.186.1 (2022-01-11) +- **react-charts:** add high contrast ([#12419](https://github.com/patternfly/patternfly-react/issues/12419)) ([e9c801c](https://github.com/patternfly/patternfly-react/commit/e9c801c84067fb9ed42d10d19deadf8dfca55289)) +# [6.5.0-prerelease.74](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.73...@patternfly/react-core@6.5.0-prerelease.74) (2026-05-08) ### Bug Fixes -* **Select:** update typeahead Select children when any option attribute changes ([#6747](https://github.com/patternfly/patternfly-react/issues/6747)) ([1e03f3c](https://github.com/patternfly/patternfly-react/commit/1e03f3c6d0a7c507e33398c98863e40bb2233a62)) - - - - - -# 4.186.0 (2022-01-11) +- Update compass.css for example CSS ([29a7f97](https://github.com/patternfly/patternfly-react/commit/29a7f9797c21ec1f12c6c40c207eb694a9155d47)) +# [6.5.0-prerelease.73](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.72...@patternfly/react-core@6.5.0-prerelease.73) (2026-05-08) ### Features -* **ToggleGroup:** support disabling all items under the parent ([#6700](https://github.com/patternfly/patternfly-react/issues/6700)) ([a60c8f3](https://github.com/patternfly/patternfly-react/commit/a60c8f3485546c797750451714a70b7e84a4ba0f)) - +- **Hero:** glass styling update ([#12412](https://github.com/patternfly/patternfly-react/issues/12412)) ([bea138e](https://github.com/patternfly/patternfly-react/commit/bea138ecd4d33a2f591dac628b875b295ec71c31)) +# [6.5.0-prerelease.72](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.71...@patternfly/react-core@6.5.0-prerelease.72) (2026-05-08) +### Features +- **Page:** add dynamic sticky section support ([#12409](https://github.com/patternfly/patternfly-react/issues/12409)) ([97b29d3](https://github.com/patternfly/patternfly-react/commit/97b29d3fafc14ee01f0bbf0d2bdbc527d62f2a16)) -## 4.185.1 (2022-01-11) +# [6.5.0-prerelease.71](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.70...@patternfly/react-core@6.5.0-prerelease.71) (2026-05-07) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.70](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.69...@patternfly/react-core@6.5.0-prerelease.70) (2026-05-07) +### Features +- **CalendarMonth:** add select appendTo passthrough ([#12391](https://github.com/patternfly/patternfly-react/issues/12391)) ([bdd5556](https://github.com/patternfly/patternfly-react/commit/bdd55564d24b112c95629d3096c4a9b66f0421e4)) +- **Pagination:** added dynamic sticky and plain ([#12388](https://github.com/patternfly/patternfly-react/issues/12388)) ([7c4f9df](https://github.com/patternfly/patternfly-react/commit/7c4f9dfac4c4a63deecd9fb4d517c5713a617f9e)) +# [6.5.0-prerelease.69](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.68...@patternfly/react-core@6.5.0-prerelease.69) (2026-05-07) -# 4.185.0 (2022-01-11) - - -### Features +**Note:** Version bump only for package @patternfly/react-core -* **Table:** update clickable area for checks/radios ([#6754](https://github.com/patternfly/patternfly-react/issues/6754)) ([c4f3c2d](https://github.com/patternfly/patternfly-react/commit/c4f3c2d7f515e3d6ad73d8b52238ca426281469a)) +# [6.5.0-prerelease.68](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.67...@patternfly/react-core@6.5.0-prerelease.68) (2026-05-05) +**Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.67](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.66...@patternfly/react-core@6.5.0-prerelease.67) (2026-05-05) +### Features +- **Drawer:** Added support for glass ([#12305](https://github.com/patternfly/patternfly-react/issues/12305)) ([bce395d](https://github.com/patternfly/patternfly-react/commit/bce395dc88c4a462b5950fb939d4e14327c7b559)) -## 4.184.2 (2022-01-10) +# [6.5.0-prerelease.66](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.65...@patternfly/react-core@6.5.0-prerelease.66) (2026-05-05) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.65](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.64...@patternfly/react-core@6.5.0-prerelease.65) (2026-05-01) +### Bug Fixes +- **demos:** improve AttributeValueFiltering menu selection and keyboard handling ([#12207](https://github.com/patternfly/patternfly-react/issues/12207)) ([2e6f8f2](https://github.com/patternfly/patternfly-react/commit/2e6f8f2fbbaedf288fff7dd681f63f1d1c7d26db)) +# [6.5.0-prerelease.64](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.63...@patternfly/react-core@6.5.0-prerelease.64) (2026-04-29) -## 4.184.1 (2022-01-10) +### Features -**Note:** Version bump only for package @patternfly/react-core +- update rhds icons to 2.2.0 ([#12387](https://github.com/patternfly/patternfly-react/issues/12387)) ([b17ea14](https://github.com/patternfly/patternfly-react/commit/b17ea14befd633e87bcb38440123ee82b2a53c3b)) +# [6.5.0-prerelease.63](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.62...@patternfly/react-core@6.5.0-prerelease.63) (2026-04-28) +### Features +- **Compass:** added responsive docked compass ([#12382](https://github.com/patternfly/patternfly-react/issues/12382)) ([ccad519](https://github.com/patternfly/patternfly-react/commit/ccad5191fb4ee814a555a8fb73fcdc4b878463ea)) +- **Toolbar,OverflowMenu:** support responsive height vis breakpoints ([#12347](https://github.com/patternfly/patternfly-react/issues/12347)) ([feca983](https://github.com/patternfly/patternfly-react/commit/feca9838a3365d7582acac578b03efeeffe1f9b5)) +- **Toolbar:** dynamic sticky ([#12375](https://github.com/patternfly/patternfly-react/issues/12375)) ([cb3856a](https://github.com/patternfly/patternfly-react/commit/cb3856aa1f6d4f419615d2ba50e9dee6d92a37be)) +# [6.5.0-prerelease.62](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.61...@patternfly/react-core@6.5.0-prerelease.62) (2026-04-27) -# 4.184.0 (2022-01-10) +**Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.61](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.60...@patternfly/react-core@6.5.0-prerelease.61) (2026-04-24) ### Features -* **Dropdown:** add plain-text variant support ([#6721](https://github.com/patternfly/patternfly-react/issues/6721)) ([e5000e3](https://github.com/patternfly/patternfly-react/commit/e5000e36194e36b9c6ae49efdb0a513125efcb70)) - +- **ToggleGroup:** added full width variant ([#12374](https://github.com/patternfly/patternfly-react/issues/12374)) ([bf01ade](https://github.com/patternfly/patternfly-react/commit/bf01adecddf38e4d5fc3bc49d68ec9982dc97485)) +# [6.5.0-prerelease.60](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.59...@patternfly/react-core@6.5.0-prerelease.60) (2026-04-24) +### Features +- **Panel, CompassPanel:** Removed CompassPanel component. Updated Panel component for use in with compass ([#12372](https://github.com/patternfly/patternfly-react/issues/12372)) ([51f4467](https://github.com/patternfly/patternfly-react/commit/51f44678475ed6cbfab6b5cdbad712a5e2535235)) -## 4.183.11 (2022-01-10) +# [6.5.0-prerelease.59](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.58...@patternfly/react-core@6.5.0-prerelease.59) (2026-04-20) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.58](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.57...@patternfly/react-core@6.5.0-prerelease.58) (2026-04-17) +### Features +- **Page:** added responsive docked nav ([#12327](https://github.com/patternfly/patternfly-react/issues/12327)) ([9f2889d](https://github.com/patternfly/patternfly-react/commit/9f2889da78275f97f85d9dde8493aa9937b8bcc2)) - -## 4.183.10 (2022-01-10) - +# [6.5.0-prerelease.57](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.56...@patternfly/react-core@6.5.0-prerelease.57) (2026-04-16) ### Bug Fixes -* **Tabs:** allow href navigation from tabs ([#6755](https://github.com/patternfly/patternfly-react/issues/6755)) ([290d89a](https://github.com/patternfly/patternfly-react/commit/290d89aed2dd4517db9859cc80ef2745cb8a779b)) - - +- **Toolbar filter:** Fixed null exception in Toolbar filter ([#12352](https://github.com/patternfly/patternfly-react/issues/12352)) ([7ed1a01](https://github.com/patternfly/patternfly-react/commit/7ed1a0178e0ce0baebb1c3223dfa58d8b07ca65c)) - - -## 4.183.9 (2022-01-10) +# [6.5.0-prerelease.56](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.55...@patternfly/react-core@6.5.0-prerelease.56) (2026-04-15) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.55](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.54...@patternfly/react-core@6.5.0-prerelease.55) (2026-04-15) +**Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.54](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.53...@patternfly/react-core@6.5.0-prerelease.54) (2026-04-14) +### Features -## 4.183.8 (2022-01-07) - -**Note:** Version bump only for package @patternfly/react-core +- **Menu toggle:** Added support for a adding styling for a menu toggle in a form ([#12326](https://github.com/patternfly/patternfly-react/issues/12326)) ([7adc580](https://github.com/patternfly/patternfly-react/commit/7adc58002949d1a5ebbf1b66d5b0d1f673d9d50e)) +# [6.5.0-prerelease.53](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.52...@patternfly/react-core@6.5.0-prerelease.53) (2026-04-13) +### Features +- **Data list:** Add isNoPlainOnGlass prop to add pf-m-no-plain modfier to the data list ([#12292](https://github.com/patternfly/patternfly-react/issues/12292)) ([f71da53](https://github.com/patternfly/patternfly-react/commit/f71da53cd09a53442ff3fffc43790b08a7465506)) +# [6.5.0-prerelease.52](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.51...@patternfly/react-core@6.5.0-prerelease.52) (2026-04-13) -## 4.183.7 (2022-01-07) +### Features -**Note:** Version bump only for package @patternfly/react-core +- **Accordion:** Added isPlain and isNoPlainOnGlass prop to Accordion ([#12288](https://github.com/patternfly/patternfly-react/issues/12288)) ([55ffb51](https://github.com/patternfly/patternfly-react/commit/55ffb51760542045f9b7dac0af584cee4a3eff4e)) +# [6.5.0-prerelease.51](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.50...@patternfly/react-core@6.5.0-prerelease.51) (2026-04-10) +### Features +- **Icons:** updated cog icons to rh settings ([#12345](https://github.com/patternfly/patternfly-react/issues/12345)) ([190da46](https://github.com/patternfly/patternfly-react/commit/190da4621acef4edd1697bb8ebccfd02299ae870)) +# [6.5.0-prerelease.50](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.49...@patternfly/react-core@6.5.0-prerelease.50) (2026-04-06) -## 4.183.6 (2022-01-07) +### Features -**Note:** Version bump only for package @patternfly/react-core +- **Page:** added styles for glass ([#12293](https://github.com/patternfly/patternfly-react/issues/12293)) ([1f7485b](https://github.com/patternfly/patternfly-react/commit/1f7485b291b5da4bb80c596a5efcc19217cabc2c)) +# [6.5.0-prerelease.49](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.48...@patternfly/react-core@6.5.0-prerelease.49) (2026-04-03) +### Features +- **Wizard:** added plain styling ([#12289](https://github.com/patternfly/patternfly-react/issues/12289)) ([4968f3c](https://github.com/patternfly/patternfly-react/commit/4968f3c482dc6d9d84b063c825a6d766908c0e13)) +# [6.5.0-prerelease.48](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.47...@patternfly/react-core@6.5.0-prerelease.48) (2026-04-01) -## 4.183.5 (2022-01-07) +**Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.47](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.46...@patternfly/react-core@6.5.0-prerelease.47) (2026-04-01) ### Bug Fixes -* **jumplinks:** Updated JumpLinks demo to allow for horizontal display ([#6731](https://github.com/patternfly/patternfly-react/issues/6731)) ([f37b934](https://github.com/patternfly/patternfly-react/commit/f37b9342e678da247056c73767d5d40ff5435bda)) +- **Menu:** adjust initially drilled-in root menu height ([#12294](https://github.com/patternfly/patternfly-react/issues/12294)) ([5c08f12](https://github.com/patternfly/patternfly-react/commit/5c08f125f7505e15bfe5c2dfb5bc5737a06b6f3a)) +# [6.5.0-prerelease.46](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.45...@patternfly/react-core@6.5.0-prerelease.46) (2026-04-01) +### Features +- **icons:** updated caret icons to RH microns ([#12298](https://github.com/patternfly/patternfly-react/issues/12298)) ([688a5af](https://github.com/patternfly/patternfly-react/commit/688a5afb40c28f0b293301d1e68f0359b7a0604d)) +# [6.5.0-prerelease.45](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.44...@patternfly/react-core@6.5.0-prerelease.45) (2026-04-01) -## 4.183.4 (2022-01-06) +### Bug Fixes -**Note:** Version bump only for package @patternfly/react-core +- **deps:** update dependency @patternfly/patternfly to v6.5.0-prerelease.62 ([#12301](https://github.com/patternfly/patternfly-react/issues/12301)) ([34b99cc](https://github.com/patternfly/patternfly-react/commit/34b99cc84c56def47cb3ec00ee99472ae72b0bd3)) +# [6.5.0-prerelease.44](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.43...@patternfly/react-core@6.5.0-prerelease.44) (2026-03-31) +### Features +- **icons:** update close icons to use the rh micron ([#12283](https://github.com/patternfly/patternfly-react/issues/12283)) ([fc82a9c](https://github.com/patternfly/patternfly-react/commit/fc82a9c646739a11732e7934d860f3913932168f)) +# [6.5.0-prerelease.43](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.42...@patternfly/react-core@6.5.0-prerelease.43) (2026-03-31) -## 4.183.3 (2022-01-06) +### Bug Fixes +- **Popper:** add null & connected checks for document ([#12284](https://github.com/patternfly/patternfly-react/issues/12284)) ([600de1b](https://github.com/patternfly/patternfly-react/commit/600de1be47e94fd8aec75a4b34b4aa40fd6412ed)) -### Bug Fixes +# [6.5.0-prerelease.42](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.41...@patternfly/react-core@6.5.0-prerelease.42) (2026-03-27) -* **TopologyControlBar:** Update screen reader className to latest ([#6739](https://github.com/patternfly/patternfly-react/issues/6739)) ([ed9da57](https://github.com/patternfly/patternfly-react/commit/ed9da575fddf9fe7af8a891972f7a66520785411)) +### Features +- **card:** add isGlass prop ([#12290](https://github.com/patternfly/patternfly-react/issues/12290)) ([f854fa6](https://github.com/patternfly/patternfly-react/commit/f854fa632902f79ec45da6aad1702699f8623e3d)) +# [6.5.0-prerelease.41](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.40...@patternfly/react-core@6.5.0-prerelease.41) (2026-03-25) +### Features +- **NotificationBadge:** add support for plain variant ([#12139](https://github.com/patternfly/patternfly-react/issues/12139)) ([43322f3](https://github.com/patternfly/patternfly-react/commit/43322f3e77e225639566aea2bdb9af0f455637d6)) -## 4.183.2 (2022-01-06) +# [6.5.0-prerelease.40](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.39...@patternfly/react-core@6.5.0-prerelease.40) (2026-03-25) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.39](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.38...@patternfly/react-core@6.5.0-prerelease.39) (2026-03-19) +### Bug Fixes +- bump pf-core version 6.5.0-prerelease.55 ([#12282](https://github.com/patternfly/patternfly-react/issues/12282)) ([852ae9a](https://github.com/patternfly/patternfly-react/commit/852ae9aacb9256d10701973c306a4480b663f583)) - -## 4.183.1 (2022-01-06) +# [6.5.0-prerelease.38](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.37...@patternfly/react-core@6.5.0-prerelease.38) (2026-03-13) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.37](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.36...@patternfly/react-core@6.5.0-prerelease.37) (2026-03-05) +### Bug Fixes +- **DescriptionList:** use correct token for termWidth ([#12253](https://github.com/patternfly/patternfly-react/issues/12253)) ([7c82404](https://github.com/patternfly/patternfly-react/commit/7c82404d085ccd25dc7e8788fc1673aa79cfe45c)) +# [6.5.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.35...@patternfly/react-core@6.5.0-prerelease.36) (2026-02-26) -# 4.183.0 (2022-01-05) - - -### Features - -* **Table:** allow a generic to be passed for cell props ([#6691](https://github.com/patternfly/patternfly-react/issues/6691)) ([e22c7be](https://github.com/patternfly/patternfly-react/commit/e22c7bebf630b7cd71e4dc434c593b69fa2fb2c8)) - +### Bug Fixes +- **CodeBlock:** remove deprecated textId prop from ClipboardCopyButton examples ([#12242](https://github.com/patternfly/patternfly-react/issues/12242)) ([cd2adc0](https://github.com/patternfly/patternfly-react/commit/cd2adc021ef18658c6ea7b0157ce990dbbd2634b)) +# [6.5.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.34...@patternfly/react-core@6.5.0-prerelease.35) (2026-02-25) +### Features -## 4.182.3 (2022-01-04) +- **Tabs:** add tabListAriaLabel prop ([#12193](https://github.com/patternfly/patternfly-react/issues/12193)) ([a7d85d7](https://github.com/patternfly/patternfly-react/commit/a7d85d7541cd62736e55e13d1564ab630fa91781)) +# [6.5.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.33...@patternfly/react-core@6.5.0-prerelease.34) (2026-02-24) ### Bug Fixes -* **docs:** fix broken theme-patternfly-org link ([#6726](https://github.com/patternfly/patternfly-react/issues/6726)) ([4ba15e9](https://github.com/patternfly/patternfly-react/commit/4ba15e9d9611afbb80d995e4d63f5478c4212a9e)) - - +- **deps:** update dependency @patternfly/patternfly to v6.5.0-prerelease.43 ([#12230](https://github.com/patternfly/patternfly-react/issues/12230)) ([82687ad](https://github.com/patternfly/patternfly-react/commit/82687ad20da22eef09581ea50266feb21d85ea8a)) +# [6.5.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.32...@patternfly/react-core@6.5.0-prerelease.33) (2026-02-18) +### Features -## 4.182.2 (2022-01-04) +- **icons:** add swap support for mapped rh-ui icons ([#12245](https://github.com/patternfly/patternfly-react/issues/12245)) ([a81ce0e](https://github.com/patternfly/patternfly-react/commit/a81ce0e1b6fdd7a3e85cdd70e5bb667dc7d82801)) -**Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.31...@patternfly/react-core@6.5.0-prerelease.32) (2026-02-06) +### Bug Fixes +- update ToggleGroup examples to properly toggle options ([#12239](https://github.com/patternfly/patternfly-react/issues/12239)) ([4332de4](https://github.com/patternfly/patternfly-react/commit/4332de4bb67b03521f99a888715019eefb9a0868)), closes [#12234](https://github.com/patternfly/patternfly-react/issues/12234) +# [6.5.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.30...@patternfly/react-core@6.5.0-prerelease.31) (2026-02-06) +### Bug Fixes -## 4.182.1 (2022-01-04) +- **LoginPage:** allow brand props passthrough make brand optional ([#12194](https://github.com/patternfly/patternfly-react/issues/12194)) ([86d09b5](https://github.com/patternfly/patternfly-react/commit/86d09b5bbc360ae076d3bbf41a6a8e04e824e4e4)) +# [6.5.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.29...@patternfly/react-core@6.5.0-prerelease.30) (2026-02-05) ### Bug Fixes -* **OverflowMenu:** pass HTMLDivElements props to group and control divs ([#6674](https://github.com/patternfly/patternfly-react/issues/6674)) ([e6d0d64](https://github.com/patternfly/patternfly-react/commit/e6d0d6406a07de04f4b232ca9a21247c0e9746c0)) +- **FileUploadField:** don't render empty dom node ([#12236](https://github.com/patternfly/patternfly-react/issues/12236)) ([57f5823](https://github.com/patternfly/patternfly-react/commit/57f5823f2f2eadbd6d2fa3ec4c8726bee72cefdf)) +# [6.5.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.28...@patternfly/react-core@6.5.0-prerelease.29) (2026-02-05) +### Features +- **TreeView:** add support for disabled TreeViewListItems ([#12140](https://github.com/patternfly/patternfly-react/issues/12140)) ([3514831](https://github.com/patternfly/patternfly-react/commit/35148312f5d9ce4e706ad36b801455fc987842bb)) +# [6.5.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.27...@patternfly/react-core@6.5.0-prerelease.28) (2026-01-12) -# 4.182.0 (2021-12-22) +**Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.26...@patternfly/react-core@6.5.0-prerelease.27) (2026-01-09) -### Features +**Note:** Version bump only for package @patternfly/react-core -* **Toolbar:** support customizing text in ToolbarChipGroupContent ([#6694](https://github.com/patternfly/patternfly-react/issues/6694)) ([24266ad](https://github.com/patternfly/patternfly-react/commit/24266adf569c027574abd1503b5e46974220349a)) +# [6.5.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.25...@patternfly/react-core@6.5.0-prerelease.26) (2026-01-09) +### Bug Fixes +- **Label:** render add variant labels as buttons ([#12192](https://github.com/patternfly/patternfly-react/issues/12192)) ([371d2c0](https://github.com/patternfly/patternfly-react/commit/371d2c09d463e03def196dba354ae9b856e9d4ac)) +# [6.5.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.24...@patternfly/react-core@6.5.0-prerelease.25) (2025-12-17) +### Features -## 4.181.5 (2021-12-16) +- **ClipboardCopy:** added textinput callbacks and props ([#12180](https://github.com/patternfly/patternfly-react/issues/12180)) ([4f5dcda](https://github.com/patternfly/patternfly-react/commit/4f5dcdae381bb12c9f728716e2be4aa5a8c67cb2)) +# [6.5.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.21...@patternfly/react-core@6.5.0-prerelease.24) (2025-12-16) ### Bug Fixes -* **LogViewer:** fix the issue that scrollbar could compress the content of the logs ([#6702](https://github.com/patternfly/patternfly-react/issues/6702)) ([11aab1f](https://github.com/patternfly/patternfly-react/commit/11aab1f71a1aa9959cf14b887ab55b845a794a00)) +- **deps:** update dependency focus-trap to v7.6.6 ([#12102](https://github.com/patternfly/patternfly-react/issues/12102)) ([06af4c5](https://github.com/patternfly/patternfly-react/commit/06af4c503674e3fdb07819b75b53a257a7822579)) +- **DrawerPanelContent:** add inert when drawer is closed ([#12027](https://github.com/patternfly/patternfly-react/issues/12027)) ([8928745](https://github.com/patternfly/patternfly-react/commit/8928745fb7364828ed4d581f30f01146bdc9990e)) +- **Drawer:** update refs in examples ([#12152](https://github.com/patternfly/patternfly-react/issues/12152)) ([2767ce0](https://github.com/patternfly/patternfly-react/commit/2767ce0896ef22bbfea5839905ee5cfedac86a80)) +- fixes broken docs link. ([#12157](https://github.com/patternfly/patternfly-react/issues/12157)) ([80b72de](https://github.com/patternfly/patternfly-react/commit/80b72de8ba9a326375cd0919ff5b81ff5b1ebf7c)) +- **form:** keep required asterisk from orphaning ([#11961](https://github.com/patternfly/patternfly-react/issues/11961)) ([d11c186](https://github.com/patternfly/patternfly-react/commit/d11c186313c9820e674fe1cdce7d630b57a62755)) +- **layouts:** update example css & classnames ([#12145](https://github.com/patternfly/patternfly-react/issues/12145)) ([11fe19a](https://github.com/patternfly/patternfly-react/commit/11fe19a02297d85f50e11375820430b2980bc47b)) +- **Wizard:** Fix crash in nav when first sub-step is hidden ([#12166](https://github.com/patternfly/patternfly-react/issues/12166)) ([3730dcf](https://github.com/patternfly/patternfly-react/commit/3730dcfe2a3f35050ba7e39fed16ead322b39521)) +### Features +- **Compass:** add isPill to Drawer by default ([#12151](https://github.com/patternfly/patternfly-react/issues/12151)) ([b2cdf1c](https://github.com/patternfly/patternfly-react/commit/b2cdf1cd5d95be91932e6ac11f39e2c0318e6f72)) +- **docked nav:** add support for docked nav layout ([#12175](https://github.com/patternfly/patternfly-react/issues/12175)) ([5519389](https://github.com/patternfly/patternfly-react/commit/55193896b899aa1e2b8dfbbddd644507988ee31f)) +# [6.5.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.20...@patternfly/react-core@6.5.0-prerelease.21) (2025-12-03) +**Note:** Version bump only for package @patternfly/react-core -## 4.181.4 (2021-12-14) +# [6.5.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.19...@patternfly/react-core@6.5.0-prerelease.20) (2025-12-03) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.18...@patternfly/react-core@6.5.0-prerelease.19) (2025-12-01) +### Features +- **Dropdown:** Add optional container with ouiaId ([#12022](https://github.com/patternfly/patternfly-react/issues/12022)) ([0811452](https://github.com/patternfly/patternfly-react/commit/0811452f2720872e19d08a3781d4399368745dc8)) +- **ExpandableSection:** Allow more control over toggle icon ([#12051](https://github.com/patternfly/patternfly-react/issues/12051)) ([07c2bbf](https://github.com/patternfly/patternfly-react/commit/07c2bbfb32491c8f69dfa4261c9e1edb9136d487)) - -## 4.181.3 (2021-12-13) +# [6.5.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.17...@patternfly/react-core@6.5.0-prerelease.18) (2025-11-21) **Note:** Version bump only for package @patternfly/react-core - - - - -## 4.181.2 (2021-12-13) +# [6.5.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.16...@patternfly/react-core@6.5.0-prerelease.17) (2025-11-20) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.15...@patternfly/react-core@6.5.0-prerelease.16) (2025-11-20) +### Features +- **Compass:** add CompassMainFooter ([#12137](https://github.com/patternfly/patternfly-react/issues/12137)) ([1da6fc2](https://github.com/patternfly/patternfly-react/commit/1da6fc2fb7d1f09ca31cc95069dab87c587639f5)) +# [6.5.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.14...@patternfly/react-core@6.5.0-prerelease.15) (2025-11-19) -## 4.181.1 (2021-12-09) +### Features -**Note:** Version bump only for package @patternfly/react-core +- **Compass:** add compass nav components ([#12138](https://github.com/patternfly/patternfly-react/issues/12138)) ([4bd98bc](https://github.com/patternfly/patternfly-react/commit/4bd98bc297261f79e4a4a7d351e336cf26a526e4)) +# [6.5.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.13...@patternfly/react-core@6.5.0-prerelease.14) (2025-11-17) +### Bug Fixes +- **Compass:** get props tables rendering correctly ([#12142](https://github.com/patternfly/patternfly-react/issues/12142)) ([399cbc4](https://github.com/patternfly/patternfly-react/commit/399cbc45844152083d0160d63f953aa7f29479d3)) +# [6.5.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.12...@patternfly/react-core@6.5.0-prerelease.13) (2025-11-14) -# 4.181.0 (2021-12-09) +### Bug Fixes +- Moves items to new nav. ([#12013](https://github.com/patternfly/patternfly-react/issues/12013)) ([ddd0696](https://github.com/patternfly/patternfly-react/commit/ddd0696796134c7d0f9583ce56e26b0df47156cb)) ### Features -* **Popover:** add composable header and alert variants ([#6664](https://github.com/patternfly/patternfly-react/issues/6664)) ([9028e8b](https://github.com/patternfly/patternfly-react/commit/9028e8ba5d674bde6a7e29532f7926e200dd632a)) +- **Compass:** updated mainheader structure to be composable ([#12135](https://github.com/patternfly/patternfly-react/issues/12135)) ([6bcdcaf](https://github.com/patternfly/patternfly-react/commit/6bcdcaf116645aad4c9c0d98ca61045976a84946)) +# [6.5.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.11...@patternfly/react-core@6.5.0-prerelease.12) (2025-11-12) +### Features +- **Hero:** added component ([#12131](https://github.com/patternfly/patternfly-react/issues/12131)) ([8da87a2](https://github.com/patternfly/patternfly-react/commit/8da87a2615bb6cfc350a52677ec6bdae335bb6f8)) +# [6.5.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.10...@patternfly/react-core@6.5.0-prerelease.11) (2025-11-10) -## 4.180.1 (2021-12-08) +### Bug Fixes -**Note:** Version bump only for package @patternfly/react-core +- Moved compass component to generative ui. ([#12133](https://github.com/patternfly/patternfly-react/issues/12133)) ([bb46849](https://github.com/patternfly/patternfly-react/commit/bb4684986bbd3fdb879aa0ff60e2747150bd3722)) +# [6.5.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.9...@patternfly/react-core@6.5.0-prerelease.10) (2025-11-10) +### Bug Fixes +- **Compass:** wrap in DrawerContentBody when drawer is passed ([#12127](https://github.com/patternfly/patternfly-react/issues/12127)) ([11e1444](https://github.com/patternfly/patternfly-react/commit/11e144430869d2f4d804c9bb6d9cc2d65a9107d0)) +# [6.5.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.8...@patternfly/react-core@6.5.0-prerelease.9) (2025-11-06) -# 4.180.0 (2021-12-08) +### Bug Fixes +- **Compass:** fix table plain example showing ([#12124](https://github.com/patternfly/patternfly-react/issues/12124)) ([8b975ca](https://github.com/patternfly/patternfly-react/commit/8b975ca685c7bb0133aeadf7ace0c91702a70f1b)) ### Features -* **DualListSelector:** add composable tree example ([#6652](https://github.com/patternfly/patternfly-react/issues/6652)) ([5fe977b](https://github.com/patternfly/patternfly-react/commit/5fe977becb5dea615724abf846f315e50931c188)) - +- **drawer:** add no-glass panel variant, test ([#12125](https://github.com/patternfly/patternfly-react/issues/12125)) ([a10ca34](https://github.com/patternfly/patternfly-react/commit/a10ca34069d25caa2954ef464d5b82a9057e0316)) +# [6.5.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.7...@patternfly/react-core@6.5.0-prerelease.8) (2025-11-06) +### Bug Fixes +- **Compass:** fix sidebars in demo ([#12117](https://github.com/patternfly/patternfly-react/issues/12117)) ([d67214f](https://github.com/patternfly/patternfly-react/commit/d67214ff47c8e1426bdf8f7894cd883d188cded3)) -## 4.179.1 (2021-12-07) +# [6.5.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.6...@patternfly/react-core@6.5.0-prerelease.7) (2025-11-05) **Note:** Version bump only for package @patternfly/react-core +# [6.5.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.5...@patternfly/react-core@6.5.0-prerelease.6) (2025-11-05) +### Features +- Added Tab updates for site Navigation ([#12111](https://github.com/patternfly/patternfly-react/issues/12111)) ([190e749](https://github.com/patternfly/patternfly-react/commit/190e7495486e83192297ea67697510f58592597b)) +# [6.5.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.4...@patternfly/react-core@6.5.0-prerelease.5) (2025-11-05) -# 4.179.0 (2021-12-06) +### Bug Fixes +- **Truncate:** remove resize observer ([#12055](https://github.com/patternfly/patternfly-react/issues/12055)) ([20fb229](https://github.com/patternfly/patternfly-react/commit/20fb229338870213bdf786343c880556f539ba16)) ### Features -* **Card:** Add disabled card and clean up props ([#6659](https://github.com/patternfly/patternfly-react/issues/6659)) ([86f225a](https://github.com/patternfly/patternfly-react/commit/86f225ab2e02d617e2d380c4a7f7593037c50e84)) +- Add plain variants for table and data list. ([#12112](https://github.com/patternfly/patternfly-react/issues/12112)) ([b0d838d](https://github.com/patternfly/patternfly-react/commit/b0d838d08e13d9060993c3ab4eb6ea7ac7b888e3)) +# [6.5.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.3...@patternfly/react-core@6.5.0-prerelease.4) (2025-11-03) +### Bug Fixes +- **ExpandableSection:** allow toggles proper dom structured headings ([#12037](https://github.com/patternfly/patternfly-react/issues/12037)) ([41f2563](https://github.com/patternfly/patternfly-react/commit/41f25637276752b2f2bc536ecf4eafac04952cbe)) +# [6.5.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.2...@patternfly/react-core@6.5.0-prerelease.3) (2025-11-03) -# 4.178.0 (2021-12-06) +### Bug Fixes +- **PageSidebar:** sidebar flash on non-mobile ([#12040](https://github.com/patternfly/patternfly-react/issues/12040)) ([f986c4f](https://github.com/patternfly/patternfly-react/commit/f986c4f30581074f2ed4d25c52333eb665be9d28)) ### Features -* **MenuToggle:** add plain with text variant ([#6627](https://github.com/patternfly/patternfly-react/issues/6627)) ([1f4ca5e](https://github.com/patternfly/patternfly-react/commit/1f4ca5e36d7077da3ff3e6918874048c784216e0)) - - +- **ExpandableSection:** functional toggleContent ([#12063](https://github.com/patternfly/patternfly-react/issues/12063)) ([3ac6454](https://github.com/patternfly/patternfly-react/commit/3ac645456f184864237dfc0c14a0b30afd60cc96)) +- **Progress:** add hideStatusIcon flag ([#12038](https://github.com/patternfly/patternfly-react/issues/12038)) ([7019b4a](https://github.com/patternfly/patternfly-react/commit/7019b4a592f283c337ae9afe227f2af193e5984f)) +# [6.5.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.5.0-prerelease.1...@patternfly/react-core@6.5.0-prerelease.2) (2025-10-31) +### Features -# 4.177.0 (2021-12-06) +- **Drawer:** Add pill version ([#12091](https://github.com/patternfly/patternfly-react/issues/12091)) ([b0a9dd8](https://github.com/patternfly/patternfly-react/commit/b0a9dd8fce6266e838ebca33ae16d1f2e0c33cbd)) +# [6.5.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.9...@patternfly/react-core@6.5.0-prerelease.1) (2025-10-30) ### Features -* **Dropdown:** add toggle variants ([#6651](https://github.com/patternfly/patternfly-react/issues/6651)) ([6414309](https://github.com/patternfly/patternfly-react/commit/64143094aec86aed86adb320e059d987af4f5f24)) +- **ActionList:** Add isVertical variant ([#12090](https://github.com/patternfly/patternfly-react/issues/12090)) ([4365bf8](https://github.com/patternfly/patternfly-react/commit/4365bf8130bde19705adac509161525d7fb47f92)) +- **Button:** added circle variant ([#12092](https://github.com/patternfly/patternfly-react/issues/12092)) ([63f79eb](https://github.com/patternfly/patternfly-react/commit/63f79eb43f9ef0a2a665cf02d09e24bddc544329)) +- **Compass:** add Compass components ([#12093](https://github.com/patternfly/patternfly-react/issues/12093)) ([ff397d8](https://github.com/patternfly/patternfly-react/commit/ff397d800b4bfbf9fc8706bc407ed00dd314623a)) +## [6.4.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.8...@patternfly/react-core@6.4.1-prerelease.9) (2025-10-24) +**Note:** Version bump only for package @patternfly/react-core +## [6.4.1-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.7...@patternfly/react-core@6.4.1-prerelease.8) (2025-10-23) +**Note:** Version bump only for package @patternfly/react-core -## 4.176.1 (2021-12-06) +## [6.4.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.6...@patternfly/react-core@6.4.1-prerelease.7) (2025-10-23) **Note:** Version bump only for package @patternfly/react-core +## [6.4.1-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.5...@patternfly/react-core@6.4.1-prerelease.6) (2025-10-23) + +**Note:** Version bump only for package @patternfly/react-core +## [6.4.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.4...@patternfly/react-core@6.4.1-prerelease.5) (2025-10-23) +**Note:** Version bump only for package @patternfly/react-core +## [6.4.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.3...@patternfly/react-core@6.4.1-prerelease.4) (2025-10-23) -# 4.176.0 (2021-12-03) +### Bug Fixes +- **Nav:** updated resizeObserver for horizontal overflow ([#12070](https://github.com/patternfly/patternfly-react/issues/12070)) ([c0d8839](https://github.com/patternfly/patternfly-react/commit/c0d8839d29b0a9ffffaded4c15a395ff025929ae)) -### Features +## [6.4.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.2...@patternfly/react-core@6.4.1-prerelease.3) (2025-10-23) -* **Select:** add ability to persist filtered children state ([#6670](https://github.com/patternfly/patternfly-react/issues/6670)) ([f618577](https://github.com/patternfly/patternfly-react/commit/f618577582e389409978bd1d6512ca0cf5d855cf)) +**Note:** Version bump only for package @patternfly/react-core +## [6.4.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.1...@patternfly/react-core@6.4.1-prerelease.2) (2025-10-22) +### Features +- **ExpandableSection:** added aria labeling ([#12071](https://github.com/patternfly/patternfly-react/issues/12071)) ([88ed152](https://github.com/patternfly/patternfly-react/commit/88ed15202972151c5b827437767347c3890eb83d)) +## [6.4.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.1-prerelease.0...@patternfly/react-core@6.4.1-prerelease.1) (2025-10-21) -## 4.175.17 (2021-12-03) +**Note:** Version bump only for package @patternfly/react-core +## [6.4.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.0...@patternfly/react-core@6.4.1-prerelease.0) (2025-10-21) ### Bug Fixes -* **Slider:** fixed examples with custom steps and input ([#6662](https://github.com/patternfly/patternfly-react/issues/6662)) ([b4cab38](https://github.com/patternfly/patternfly-react/commit/b4cab38a2492564bf91e3711ce322951bcc6a051)) +- **DrawerPanelContent:** fix issue with styles overriding ([#12039](https://github.com/patternfly/patternfly-react/issues/12039)) ([fb91a1d](https://github.com/patternfly/patternfly-react/commit/fb91a1d4245d858c12b1c061f4f3c52c2be55033)) +- **Progress:** Fixed to use the correct icon for danger variant ([#12073](https://github.com/patternfly/patternfly-react/issues/12073)) ([46edc2b](https://github.com/patternfly/patternfly-react/commit/46edc2b1bb04dc61e36b07a63b6bfe2ffc8cdc60)) +### Features +- **Radio/Checkbox:** support for aria-describedBy ([#12042](https://github.com/patternfly/patternfly-react/issues/12042)) ([286de49](https://github.com/patternfly/patternfly-react/commit/286de49c017ba4b3ba06b434de9600a7d6adce1a)) +- **Wizard:** warning step status ([#12041](https://github.com/patternfly/patternfly-react/issues/12041)) ([3d202a8](https://github.com/patternfly/patternfly-react/commit/3d202a8b57174ff1670157110ca54e4b7aba4a90)) +# [6.4.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.0-prerelease.5...@patternfly/react-core@6.4.0) (2025-10-16) +**Note:** Version bump only for package @patternfly/react-core -## 4.175.16 (2021-12-02) +# [6.4.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.0-prerelease.4...@patternfly/react-core@6.4.0-prerelease.5) (2025-10-16) **Note:** Version bump only for package @patternfly/react-core +# [6.4.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.0-prerelease.3...@patternfly/react-core@6.4.0-prerelease.4) (2025-10-13) +### Bug Fixes +- **examples:** make sure examples with SearchInput have onClear ([#12044](https://github.com/patternfly/patternfly-react/issues/12044)) ([9c785af](https://github.com/patternfly/patternfly-react/commit/9c785af077869005514bc719212e21f9193f9206)) +# [6.4.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.0-prerelease.2...@patternfly/react-core@6.4.0-prerelease.3) (2025-10-10) -## 4.175.15 (2021-12-02) +**Note:** Version bump only for package @patternfly/react-core +# [6.4.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.0-prerelease.1...@patternfly/react-core@6.4.0-prerelease.2) (2025-10-01) ### Bug Fixes -* **Tile:** fix selecting tile in tile demo ([#6653](https://github.com/patternfly/patternfly-react/issues/6653)) ([e12e44d](https://github.com/patternfly/patternfly-react/commit/e12e44d4b623de305b7df04174144a9496d282a7)) - +- Bumped echarts and core. ([#12023](https://github.com/patternfly/patternfly-react/issues/12023)) ([1d4d075](https://github.com/patternfly/patternfly-react/commit/1d4d075730c3645394c774bfc5233ea786e29e43)) +# [6.4.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.22...@patternfly/react-core@6.4.0-prerelease.1) (2025-09-26) +### Bug Fixes +- updated to 6.4.0-prerelease ([df46ac6](https://github.com/patternfly/patternfly-react/commit/df46ac6bed381eb3e01e5573f77d79301b02b7fa)) -## 4.175.14 (2021-12-01) +## [6.3.1-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.21...@patternfly/react-core@6.3.1-prerelease.22) (2025-09-26) **Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.20...@patternfly/react-core@6.3.1-prerelease.21) (2025-09-25) +### Bug Fixes +- **MenuGroup:** fix title generation when the string is empty ([#11999](https://github.com/patternfly/patternfly-react/issues/11999)) ([b74d8b8](https://github.com/patternfly/patternfly-react/commit/b74d8b8e02f18570e0125af47464612fff59bbc0)) +## [6.3.1-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.19...@patternfly/react-core@6.3.1-prerelease.20) (2025-09-25) -## 4.175.13 (2021-11-30) +### Bug Fixes -**Note:** Version bump only for package @patternfly/react-core +- **Truncate:** Update truncate examples to use PF6 tokens to match core ([#11943](https://github.com/patternfly/patternfly-react/issues/11943)) ([d3c0109](https://github.com/patternfly/patternfly-react/commit/d3c010945f069bf6b6c21aa4506c9a6391841d53)) +## [6.3.1-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.18...@patternfly/react-core@6.3.1-prerelease.19) (2025-09-24) +### Bug Fixes +- **Select:** improve type consistency in `onSelect` ([#11935](https://github.com/patternfly/patternfly-react/issues/11935)) ([d50ba6d](https://github.com/patternfly/patternfly-react/commit/d50ba6db350ae355b63d3d2ffd0f9095866da074)) +## [6.3.1-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.17...@patternfly/react-core@6.3.1-prerelease.18) (2025-09-24) -## 4.175.12 (2021-11-30) +**Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.16...@patternfly/react-core@6.3.1-prerelease.17) (2025-09-24) ### Bug Fixes -* **action-list:** added support for classname ([#6647](https://github.com/patternfly/patternfly-react/issues/6647)) ([dd3d2ce](https://github.com/patternfly/patternfly-react/commit/dd3d2ce32b4d3e7562faf465abdc508e17f097d9)) - - +- **MenuItemAction:** update to use new favorite button props ([#11998](https://github.com/patternfly/patternfly-react/issues/11998)) ([d49cdd4](https://github.com/patternfly/patternfly-react/commit/d49cdd49fb7771a9c5e787b07c143b560d397c51)) +## [6.3.1-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.15...@patternfly/react-core@6.3.1-prerelease.16) (2025-09-24) +### Features -## 4.175.11 (2021-11-30) +- extend `PopperProps` in derivative component types ([#11934](https://github.com/patternfly/patternfly-react/issues/11934)) ([b79c4d6](https://github.com/patternfly/patternfly-react/commit/b79c4d63dcc787b49a311103e3a168d511b6d07a)) -**Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.14...@patternfly/react-core@6.3.1-prerelease.15) (2025-09-23) +### Features +- **AnimationsProvider:** Add Support for AnimationsProvider ([#11990](https://github.com/patternfly/patternfly-react/issues/11990)) ([fdd6433](https://github.com/patternfly/patternfly-react/commit/fdd6433709c7f59536930119e2fb7ad0260fea15)) +## [6.3.1-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.13...@patternfly/react-core@6.3.1-prerelease.14) (2025-09-11) +### Bug Fixes -## 4.175.10 (2021-11-23) +- **tabs:** spread style prop ([#11981](https://github.com/patternfly/patternfly-react/issues/11981)) ([fff4426](https://github.com/patternfly/patternfly-react/commit/fff44264869d6dbaf2f8cfc5c957f71fdb5b3257)) -**Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.12...@patternfly/react-core@6.3.1-prerelease.13) (2025-09-11) +### Bug Fixes +- **Menu:** prevent flyout crash when mixing keyboard and mouse interaction ([#11993](https://github.com/patternfly/patternfly-react/issues/11993)) ([d23dd72](https://github.com/patternfly/patternfly-react/commit/d23dd72afdc5740bb0cb05d48f933cc2547aeb98)) +## [6.3.1-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.11...@patternfly/react-core@6.3.1-prerelease.12) (2025-09-10) +### Bug Fixes -## 4.175.9 (2021-11-19) +- **Truncate:** pass forwardRef properly ([#11992](https://github.com/patternfly/patternfly-react/issues/11992)) ([2af86aa](https://github.com/patternfly/patternfly-react/commit/2af86aaf7a0f8e10a5977975c3a3aa0fa22582b8)) -**Note:** Version bump only for package @patternfly/react-core +### Features +- **Popper:** add passthrough for offset ([#11994](https://github.com/patternfly/patternfly-react/issues/11994)) ([087949d](https://github.com/patternfly/patternfly-react/commit/087949d601a7196de285d78e737fda9392b7adcf)) +## [6.3.1-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.10...@patternfly/react-core@6.3.1-prerelease.11) (2025-09-10) +### Bug Fixes +- **DataList:** allow keyboard to trigger DataListActions ([#11974](https://github.com/patternfly/patternfly-react/issues/11974)) ([cd59c2f](https://github.com/patternfly/patternfly-react/commit/cd59c2fd153f6f898841b37a9694c9dcf7cb60e4)) -## 4.175.8 (2021-11-19) +## [6.3.1-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.9...@patternfly/react-core@6.3.1-prerelease.10) (2025-09-10) **Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.8...@patternfly/react-core@6.3.1-prerelease.9) (2025-09-09) +### Bug Fixes +- **ClipboardCopy:** Adjust aria-labels on buttons ([#11996](https://github.com/patternfly/patternfly-react/issues/11996)) ([2ac9dcb](https://github.com/patternfly/patternfly-react/commit/2ac9dcb728cf6f360f96d53476c78747a36042b3)) +## [6.3.1-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.7...@patternfly/react-core@6.3.1-prerelease.8) (2025-09-05) -## 4.175.7 (2021-11-18) +**Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.6...@patternfly/react-core@6.3.1-prerelease.7) (2025-08-26) -### Bug Fixes +**Note:** Version bump only for package @patternfly/react-core -* **pagination:** updated toggleTemplate prop description to include ofWord prop ([#6622](https://github.com/patternfly/patternfly-react/issues/6622)) ([26733a6](https://github.com/patternfly/patternfly-react/commit/26733a6a256ad0e873afbc268a712027470fdeaa)) +## [6.3.1-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.5...@patternfly/react-core@6.3.1-prerelease.6) (2025-08-18) +### Bug Fixes +- **Tabs:** updated logic for uncontrolled tabs animation ([#11958](https://github.com/patternfly/patternfly-react/issues/11958)) ([c5a7e63](https://github.com/patternfly/patternfly-react/commit/c5a7e6395b118929a6a87db1c9a06a6dcc662d64)) +## [6.3.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.4...@patternfly/react-core@6.3.1-prerelease.5) (2025-08-18) +### Bug Fixes -## 4.175.6 (2021-11-18) +- **JumpLinks:** Fix aria issues ([#11950](https://github.com/patternfly/patternfly-react/issues/11950)) ([8bdb879](https://github.com/patternfly/patternfly-react/commit/8bdb879bada1a9322cdb31cd27beea73e2209405)) -**Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.3...@patternfly/react-core@6.3.1-prerelease.4) (2025-08-12) +### Bug Fixes +- **Tooltip:** added aria attributes for triggerRef ([#11953](https://github.com/patternfly/patternfly-react/issues/11953)) ([08a10a8](https://github.com/patternfly/patternfly-react/commit/08a10a8d60e5d2f32bafcd7ce10c46fa7784e2fb)) +## [6.3.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.2...@patternfly/react-core@6.3.1-prerelease.3) (2025-08-05) +### Bug Fixes -## 4.175.5 (2021-11-17) +- **PrimaryDetail:** added padding to correct toolbar alignment in card demo ([#11939](https://github.com/patternfly/patternfly-react/issues/11939)) ([325f71b](https://github.com/patternfly/patternfly-react/commit/325f71b2c8da9305aee7bae3aad2a346761e7206)) -**Note:** Version bump only for package @patternfly/react-core +## [6.3.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.1...@patternfly/react-core@6.3.1-prerelease.2) (2025-08-05) +### Bug Fixes +- **LabelGroup:** updated close icon ([#11942](https://github.com/patternfly/patternfly-react/issues/11942)) ([270d544](https://github.com/patternfly/patternfly-react/commit/270d5446d0ed54197c8c70fef034be53edaf6a2b)) +## [6.3.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.1-prerelease.0...@patternfly/react-core@6.3.1-prerelease.1) (2025-08-04) +### Bug Fixes -## 4.175.4 (2021-11-15) +- **Page:** pass sidebar state to button for isHamburger ([#11951](https://github.com/patternfly/patternfly-react/issues/11951)) ([60806c2](https://github.com/patternfly/patternfly-react/commit/60806c2dbf360fdbeea314119a6d0d238106de2d)) +## [6.3.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0...@patternfly/react-core@6.3.1-prerelease.0) (2025-07-28) ### Bug Fixes -* **FileUpload:** Downgrade react-dropzone back to 9.0.0 to avoid a breaking type change, fix behavior regressions ([#6610](https://github.com/patternfly/patternfly-react/issues/6610)) ([574bf4f](https://github.com/patternfly/patternfly-react/commit/574bf4ff3ccf7f67ce750bc48067eaf826e99990)) +- **Card:** Add ref forwarding ([#11879](https://github.com/patternfly/patternfly-react/issues/11879)) ([deec405](https://github.com/patternfly/patternfly-react/commit/deec405b30c9324ded1cbff307a781c1c4d75e1e)) +- **textarea:** fix height logic for autoresize textarea ([#11922](https://github.com/patternfly/patternfly-react/issues/11922)) ([be2b744](https://github.com/patternfly/patternfly-react/commit/be2b744368d90c3a003c4eb73d054c7e11889a2d)) +# 6.3.0 (2025-07-22) +**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.4.0-prerelease.0...@patternfly/react-core@6.3.0-prerelease.34) (2025-07-22) +### Reverts -## 4.175.3 (2021-11-15) +- Revert "chore(release): releasing packages [ci skip]" ([40999d7](https://github.com/patternfly/patternfly-react/commit/40999d70a7a3aeadbe8f40fe96bb01ab3a6219d4)) +# [6.3.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.32...@patternfly/react-core@6.3.0-prerelease.33) (2025-07-18) ### Bug Fixes -* **Menu:** allow maxMenuHeight with Scrollabe ([#6608](https://github.com/patternfly/patternfly-react/issues/6608)) ([8c1f12c](https://github.com/patternfly/patternfly-react/commit/8c1f12c2b0e86bbc5ba1071db3ebf29fee7421a0)) - +- **Button:** Bump core version to fix button animation ([#11928](https://github.com/patternfly/patternfly-react/issues/11928)) ([dc6e358](https://github.com/patternfly/patternfly-react/commit/dc6e358e8b9cd81f9be0a1a21d4fc0cae4ca21d8)) +# [6.3.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.31...@patternfly/react-core@6.3.0-prerelease.32) (2025-07-17) +### Bug Fixes +- **Tables:** updated animations to beta ([#11927](https://github.com/patternfly/patternfly-react/issues/11927)) ([cca6678](https://github.com/patternfly/patternfly-react/commit/cca667858c24bb9d7cb39e0c781ff3c8466f7ef6)) -## 4.175.2 (2021-11-15) +# [6.3.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.30...@patternfly/react-core@6.3.0-prerelease.31) (2025-07-16) -**Note:** Version bump only for package @patternfly/react-core +### Bug Fixes +- resolve memory leaks in event listeners and observers ([#11926](https://github.com/patternfly/patternfly-react/issues/11926)) ([70db4bd](https://github.com/patternfly/patternfly-react/commit/70db4bd9c06ada23d79ad0c2d6bf1d601a157560)) +# [6.3.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.29...@patternfly/react-core@6.3.0-prerelease.30) (2025-07-11) +### Bug Fixes +- **Table:** updated logic for expandable class ([#11918](https://github.com/patternfly/patternfly-react/issues/11918)) ([2b6c99b](https://github.com/patternfly/patternfly-react/commit/2b6c99b4617f09009d799af4587a0b0d291cdf84)) -## 4.175.1 (2021-11-15) +# [6.3.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.28...@patternfly/react-core@6.3.0-prerelease.29) (2025-07-02) **Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.27...@patternfly/react-core@6.3.0-prerelease.28) (2025-07-01) +**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.26...@patternfly/react-core@6.3.0-prerelease.27) (2025-06-23) +### Bug Fixes -# 4.175.0 (2021-11-12) +- Bumped to latest core version. ([#11880](https://github.com/patternfly/patternfly-react/issues/11880)) ([0380aa5](https://github.com/patternfly/patternfly-react/commit/0380aa504b4d0d83459126bfd98b2e4e29cac4e8)) +# [6.3.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.25...@patternfly/react-core@6.3.0-prerelease.26) (2025-06-20) ### Features -* **card:** added hoverable/selectable/selected-raised variant ([#6565](https://github.com/patternfly/patternfly-react/issues/6565)) ([8c60568](https://github.com/patternfly/patternfly-react/commit/8c60568ba4fa18398fed636710e222ce506de82c)) +- **Table:** added optin animations for expansion ([#11865](https://github.com/patternfly/patternfly-react/issues/11865)) ([9adc88b](https://github.com/patternfly/patternfly-react/commit/9adc88b652f77ed5737c9f6dd02885daace1cd2b)) +# [6.3.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.24...@patternfly/react-core@6.3.0-prerelease.25) (2025-06-18) +### Features + +- **SearchInput:** enable animations ([#11874](https://github.com/patternfly/patternfly-react/issues/11874)) ([50ddd0f](https://github.com/patternfly/patternfly-react/commit/50ddd0f2b8f0c0e53caf4be6a9fa4b2b15f13ceb)) +# [6.3.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.23...@patternfly/react-core@6.3.0-prerelease.24) (2025-06-17) +### Features -## 4.174.2 (2021-11-12) +- **Tabs:** add the option to disable the Add button ([#11872](https://github.com/patternfly/patternfly-react/issues/11872)) ([1337e36](https://github.com/patternfly/patternfly-react/commit/1337e36f4434b1b92afe9fe67d4c4f17b05ab95f)) -**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.22...@patternfly/react-core@6.3.0-prerelease.23) (2025-06-17) +### Bug Fixes +- **ExpandableSection:** made animation opt-in for detached variant ([#11851](https://github.com/patternfly/patternfly-react/issues/11851)) ([64befbe](https://github.com/patternfly/patternfly-react/commit/64befbe8547ebf4c388ed9f039253a7a689440f8)) +# [6.3.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.21...@patternfly/react-core@6.3.0-prerelease.22) (2025-06-16) +### Features -## 4.174.1 (2021-11-12) +- **TreeView:** enabled opt-in animations ([#11842](https://github.com/patternfly/patternfly-react/issues/11842)) ([bfc382c](https://github.com/patternfly/patternfly-react/commit/bfc382c9b3c0de4b22babb8f72085654e7e89c7a)) -**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.20...@patternfly/react-core@6.3.0-prerelease.21) (2025-06-13) +### Features +- **Button/MenuToggle:** added support for hamburger/settings animations ([#11861](https://github.com/patternfly/patternfly-react/issues/11861)) ([cf3d84e](https://github.com/patternfly/patternfly-react/commit/cf3d84ebf8f3046f038af6f6557946faadfe35b0)) +# [6.3.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.19...@patternfly/react-core@6.3.0-prerelease.20) (2025-06-13) +### Features -# 4.174.0 (2021-11-11) +- **Icons:** Allow more complex paths and svgs ([#11864](https://github.com/patternfly/patternfly-react/issues/11864)) ([fa16a3b](https://github.com/patternfly/patternfly-react/commit/fa16a3bd3ac35be6f0d23f642194d23dba0b313e)) +# [6.3.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.18...@patternfly/react-core@6.3.0-prerelease.19) (2025-06-13) ### Features -* **ComposableTable:** add sticky columns and nested headers ([#6538](https://github.com/patternfly/patternfly-react/issues/6538)) ([f11245b](https://github.com/patternfly/patternfly-react/commit/f11245bfccc8c6c02a9d5545a69ed533743cc552)) - +- **button:** add favorite variant ([#11853](https://github.com/patternfly/patternfly-react/issues/11853)) ([84c5af6](https://github.com/patternfly/patternfly-react/commit/84c5af6da67db4638248a8025392cb84443dd85d)) +# [6.3.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.17...@patternfly/react-core@6.3.0-prerelease.18) (2025-06-11) +### Features +- **Form:** enabled opt-in animations for expandable fieldgroup ([#11843](https://github.com/patternfly/patternfly-react/issues/11843)) ([8c6618b](https://github.com/patternfly/patternfly-react/commit/8c6618b87876924b7ef9b3651b86abb65e7e2dd4)) -# 4.173.0 (2021-11-11) +# [6.3.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.16...@patternfly/react-core@6.3.0-prerelease.17) (2025-06-02) +### Bug Fixes -### Features +- **TreeViewListItem:** customBadgeContent of number 0 will display ([#11848](https://github.com/patternfly/patternfly-react/issues/11848)) ([134960a](https://github.com/patternfly/patternfly-react/commit/134960a845d5e94f3979f1719f978a11987b2f70)) -* **contextselector:** added support for context selector items as links ([#6554](https://github.com/patternfly/patternfly-react/issues/6554)) ([c465388](https://github.com/patternfly/patternfly-react/commit/c4653881eee0cd8ec8e3a7125bbef0bded9f2de0)) +# [6.3.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.15...@patternfly/react-core@6.3.0-prerelease.16) (2025-05-29) +### Bug Fixes +- added resultsCountContext prop to pass into the screenReaderText… ([#11844](https://github.com/patternfly/patternfly-react/issues/11844)) ([d96668a](https://github.com/patternfly/patternfly-react/commit/d96668aa1ddaba5bea8b1c921e8f2145d44587ad)) +- **Popper:** resolved alignment issue for multiple renders ([#11846](https://github.com/patternfly/patternfly-react/issues/11846)) ([df45676](https://github.com/patternfly/patternfly-react/commit/df45676f2eddf21226117a97d2af2490982b14c1)) +# [6.3.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.14...@patternfly/react-core@6.3.0-prerelease.15) (2025-05-29) +### Features -# 4.172.0 (2021-11-11) +- **DualListSelector:** enabled opt-in animations ([#11837](https://github.com/patternfly/patternfly-react/issues/11837)) ([a545f05](https://github.com/patternfly/patternfly-react/commit/a545f05d90343c6fc80ddd337c61118694f876e2)) +# [6.3.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.13...@patternfly/react-core@6.3.0-prerelease.14) (2025-05-21) ### Features -* **Navigation:** Added exemple with third level ([#6564](https://github.com/patternfly/patternfly-react/issues/6564)) ([c30da53](https://github.com/patternfly/patternfly-react/commit/c30da532855118f705c8cfc87c545bb1eea11ebb)) - +- **Tabs:** added animations ([#11767](https://github.com/patternfly/patternfly-react/issues/11767)) ([bae4fc3](https://github.com/patternfly/patternfly-react/commit/bae4fc36aa39007d9474236cbada62ac55a27989)) +# [6.3.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.12...@patternfly/react-core@6.3.0-prerelease.13) (2025-05-21) +### Features +- **Truncate:** added tooltip props and anchor usage ([#11801](https://github.com/patternfly/patternfly-react/issues/11801)) ([e8c5538](https://github.com/patternfly/patternfly-react/commit/e8c55388ac92023343b85778c071076d22405363)) -# 4.171.0 (2021-11-11) +# [6.3.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.11...@patternfly/react-core@6.3.0-prerelease.12) (2025-05-20) +### Bug Fixes -### Features +- **Table:** removed divider for expanded rows ([#11815](https://github.com/patternfly/patternfly-react/issues/11815)) ([292dd5e](https://github.com/patternfly/patternfly-react/commit/292dd5ebf809d9bffa6698d7c6fea6da82f73c64)) -* enhance type correctness of CodeEditor ([#6579](https://github.com/patternfly/patternfly-react/issues/6579)) ([e1ad65c](https://github.com/patternfly/patternfly-react/commit/e1ad65c225968d5a9c74019d19e4a3c5e2666926)) +# [6.3.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.10...@patternfly/react-core@6.3.0-prerelease.11) (2025-05-16) +**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.9...@patternfly/react-core@6.3.0-prerelease.10) (2025-05-15) +**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.8...@patternfly/react-core@6.3.0-prerelease.9) (2025-05-15) -## 4.170.4 (2021-11-10) +**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.7...@patternfly/react-core@6.3.0-prerelease.8) (2025-05-13) ### Bug Fixes -* **jumplinks:** fixed to always set clicked item as active ([#6542](https://github.com/patternfly/patternfly-react/issues/6542)) ([845c98f](https://github.com/patternfly/patternfly-react/commit/845c98f5f3df8aa9b6acc190707c5f1d7bf3ca38)) +- **Truncate:** allowed punctuation at start of content ([#11798](https://github.com/patternfly/patternfly-react/issues/11798)) ([a66ce81](https://github.com/patternfly/patternfly-react/commit/a66ce819a3898887307dd1acb6ffea8376b1c2f3)) +# [6.3.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.6...@patternfly/react-core@6.3.0-prerelease.7) (2025-05-07) +**Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.5...@patternfly/react-core@6.3.0-prerelease.6) (2025-05-07) +### Features -## 4.170.3 (2021-11-10) +- **MultiTypeaheadSelect:** make labels removable and customizable ([#11774](https://github.com/patternfly/patternfly-react/issues/11774)) ([354f4f9](https://github.com/patternfly/patternfly-react/commit/354f4f9553cecd476bf0cf9169796b2523917398)) +# [6.3.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.4...@patternfly/react-core@6.3.0-prerelease.5) (2025-05-07) ### Bug Fixes -* **Menu:** stop passing disableHover to DrilldownMenu DOM ([#6571](https://github.com/patternfly/patternfly-react/issues/6571)) ([63dcf25](https://github.com/patternfly/patternfly-react/commit/63dcf256723848ff3789828fc0a5f86d5009fc87)) +- **login page:** update demo background ([#11781](https://github.com/patternfly/patternfly-react/issues/11781)) ([8133dde](https://github.com/patternfly/patternfly-react/commit/8133dde55792cf45e812c2b8af1fcfbc52adc513)) +# [6.3.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.3...@patternfly/react-core@6.3.0-prerelease.4) (2025-04-30) +**Note:** Version bump only for package @patternfly/react-core + +# [6.3.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.2...@patternfly/react-core@6.3.0-prerelease.3) (2025-04-30) +### Bug Fixes +- **password generator:** fixed syntax error in demo ([#11782](https://github.com/patternfly/patternfly-react/issues/11782)) ([008965c](https://github.com/patternfly/patternfly-react/commit/008965c54caec4ca07bc5403677e4bab1aa6b44b)) -## 4.170.2 (2021-11-10) +# [6.3.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.3.0-prerelease.1...@patternfly/react-core@6.3.0-prerelease.2) (2025-04-28) **Note:** Version bump only for package @patternfly/react-core +# [6.3.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.12...@patternfly/react-core@6.3.0-prerelease.1) (2025-04-24) + +**Note:** Version bump only for package @patternfly/react-core +## [6.2.1-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.11...@patternfly/react-core@6.2.1-prerelease.12) (2025-04-23) +### Bug Fixes +- **Truncate, Progress:** enable truncated tooltip via keyboard ([#11731](https://github.com/patternfly/patternfly-react/issues/11731)) ([dffaa90](https://github.com/patternfly/patternfly-react/commit/dffaa90933fe7552dfece930ff71d190664c409a)) -## 4.170.1 (2021-11-10) +## [6.2.1-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.10...@patternfly/react-core@6.2.1-prerelease.11) (2025-04-22) **Note:** Version bump only for package @patternfly/react-core +## [6.2.1-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.9...@patternfly/react-core@6.2.1-prerelease.10) (2025-04-21) +**Note:** Version bump only for package @patternfly/react-core +## [6.2.1-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.8...@patternfly/react-core@6.2.1-prerelease.9) (2025-04-21) +**Note:** Version bump only for package @patternfly/react-core -# 4.170.0 (2021-11-09) - +## [6.2.1-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.7...@patternfly/react-core@6.2.1-prerelease.8) (2025-04-21) ### Features -* **Table:** set default sort direction ([#6544](https://github.com/patternfly/patternfly-react/issues/6544)) ([9ee4942](https://github.com/patternfly/patternfly-react/commit/9ee49428c8e1041721f2a09f8176a5aba3335049)) - +- **version:** testing react 19 ([#11754](https://github.com/patternfly/patternfly-react/issues/11754)) ([b981588](https://github.com/patternfly/patternfly-react/commit/b9815886da3adc7a96bc2d48adacf86e8a752e61)) +## [6.2.1-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.6...@patternfly/react-core@6.2.1-prerelease.7) (2025-04-21) +### Features +- **Truncate:** added logic to truncate based on max characters ([#11742](https://github.com/patternfly/patternfly-react/issues/11742)) ([b7456f9](https://github.com/patternfly/patternfly-react/commit/b7456f99ce61449ced092153bebb1a40b1c96ade)) -## 4.169.4 (2021-11-09) +## [6.2.1-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.5...@patternfly/react-core@6.2.1-prerelease.6) (2025-04-17) -**Note:** Version bump only for package @patternfly/react-core +### Bug Fixes +- **Nav:** added role presentation to NavItemSeparator ([#11730](https://github.com/patternfly/patternfly-react/issues/11730)) ([076070c](https://github.com/patternfly/patternfly-react/commit/076070c8823557608717b258b22c5d9949d986c5)) +## [6.2.1-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.4...@patternfly/react-core@6.2.1-prerelease.5) (2025-04-15) +### Bug Fixes +- **Wizard deprecated:** added wrapper for step name ([#11761](https://github.com/patternfly/patternfly-react/issues/11761)) ([d0b7b70](https://github.com/patternfly/patternfly-react/commit/d0b7b70a7f108f49b5d3729d803ff6126bdd8192)) -## 4.169.3 (2021-11-08) +## [6.2.1-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.3...@patternfly/react-core@6.2.1-prerelease.4) (2025-04-14) -**Note:** Version bump only for package @patternfly/react-core +### Features +- **Page:** Added support for sidebar-less layout ([#11760](https://github.com/patternfly/patternfly-react/issues/11760)) ([217aad3](https://github.com/patternfly/patternfly-react/commit/217aad3241e79b02ab8f1f74fd1d8022860a138b)) +## [6.2.1-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.2...@patternfly/react-core@6.2.1-prerelease.3) (2025-04-11) +### Features +- **LoginPage:** added isPasswordRequired prop ([#11673](https://github.com/patternfly/patternfly-react/issues/11673)) ([0658fb3](https://github.com/patternfly/patternfly-react/commit/0658fb347e2db799dcb6626fc30c5837592a1e3c)) -## 4.169.2 (2021-11-08) +## [6.2.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.1...@patternfly/react-core@6.2.1-prerelease.2) (2025-04-10) **Note:** Version bump only for package @patternfly/react-core +## [6.2.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.1-prerelease.0...@patternfly/react-core@6.2.1-prerelease.1) (2025-04-08) +### Bug Fixes +- **DatePicker:** prevented textless helper text from rendering ([#11713](https://github.com/patternfly/patternfly-react/issues/11713)) ([7be0f9c](https://github.com/patternfly/patternfly-react/commit/7be0f9ce666b5ba51fcf1c714c210d5f2ea4a490)) - -## 4.169.1 (2021-11-08) - +## [6.2.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0...@patternfly/react-core@6.2.1-prerelease.0) (2025-04-08) ### Bug Fixes -* **acccessconsoles:** use object type Select options values in order to not mix displayed text with option keys ([#6496](https://github.com/patternfly/patternfly-react/issues/6496)) ([975c8e1](https://github.com/patternfly/patternfly-react/commit/975c8e14d7ea8c53eb4048ea6ef73e804b3ad2be)) - +- **HelperTextItem:** allowed removal of SR text element ([#11704](https://github.com/patternfly/patternfly-react/issues/11704)) ([5dd8f3e](https://github.com/patternfly/patternfly-react/commit/5dd8f3e8ae1c2d090288cbe8fbaedd836c93bdb6)) +# 6.2.0 (2025-04-07) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.36](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.35...@patternfly/react-core@6.2.0-prerelease.36) (2025-04-01) -# 4.169.0 (2021-11-04) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.35](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.34...@patternfly/react-core@6.2.0-prerelease.35) (2025-03-26) -### Features +**Note:** Version bump only for package @patternfly/react-core -* **log-viewer:** support ANSI color ([#6519](https://github.com/patternfly/patternfly-react/issues/6519)) ([936a699](https://github.com/patternfly/patternfly-react/commit/936a699b0514a492d3c40be08932fb7bab275cce)) +# [6.2.0-prerelease.34](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.33...@patternfly/react-core@6.2.0-prerelease.34) (2025-03-20) +### Bug Fixes +- **deps:** Apply JSX tranform changes to missed demos and examples ([#11679](https://github.com/patternfly/patternfly-react/issues/11679)) ([546aaa1](https://github.com/patternfly/patternfly-react/commit/546aaa163f9a4cdb3649190783e5d9d5f32b9b6a)) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.20 ([#11653](https://github.com/patternfly/patternfly-react/issues/11653)) ([f4df244](https://github.com/patternfly/patternfly-react/commit/f4df244b1fe68c1ac34bff7379f2bb6558676fb2)) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.23 ([#11660](https://github.com/patternfly/patternfly-react/issues/11660)) ([01006e6](https://github.com/patternfly/patternfly-react/commit/01006e6ec3085a3e25fb47904206e5476013e0eb)) +### Features +- **Alert:** added animations ([#11495](https://github.com/patternfly/patternfly-react/issues/11495)) ([74dd258](https://github.com/patternfly/patternfly-react/commit/74dd258abb9f329dc2fc3fcaaa6fc4de460fc088)) +- **card:** add hasHeaderWrap prop and test to support card header wrapping ([#11663](https://github.com/patternfly/patternfly-react/issues/11663)) ([d341d0b](https://github.com/patternfly/patternfly-react/commit/d341d0bf83bb0ebc0bb7b769bbfaf3eda7a2d906)) +- **ClipboardCopy:** added truncation for inlinecompact variant ([#11610](https://github.com/patternfly/patternfly-react/issues/11610)) ([48b5749](https://github.com/patternfly/patternfly-react/commit/48b5749dfda3841aaaeea995659f2094272dc999)) +- **NotificationBadge:** Add animation for notify ([#11675](https://github.com/patternfly/patternfly-react/issues/11675)) ([37ad42b](https://github.com/patternfly/patternfly-react/commit/37ad42bb7ee7ca27882e54470cfa11cf50789070)) +- **toolbar:** add hasNoPadding prop and test ([#11648](https://github.com/patternfly/patternfly-react/issues/11648)) ([177b684](https://github.com/patternfly/patternfly-react/commit/177b684a67313f3655a3df75d43864309d771902)) -## 4.168.11 (2021-11-01) +# [6.2.0-prerelease.33](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.32...@patternfly/react-core@6.2.0-prerelease.33) (2025-03-11) +### Features -### Bug Fixes +- **Toolbar:** Add row wrap prop to ToolbarGroup and ToolbarItem ([#11559](https://github.com/patternfly/patternfly-react/issues/11559)) ([6b1646f](https://github.com/patternfly/patternfly-react/commit/6b1646faec6a620a9438ca5a01faf52afb1aa992)) -* **AboutModal:** allow to disable FocusTrap ([#6509](https://github.com/patternfly/patternfly-react/issues/6509)) ([72536e1](https://github.com/patternfly/patternfly-react/commit/72536e1f73641ff3f19f865f08dbb41ad0ee7b9f)) +# [6.2.0-prerelease.32](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.31...@patternfly/react-core@6.2.0-prerelease.32) (2025-03-11) +### Features +- **DataList:** add tooltip to truncated DataListCell ([#11643](https://github.com/patternfly/patternfly-react/issues/11643)) ([542f96d](https://github.com/patternfly/patternfly-react/commit/542f96dffd57135cce70ec7aea8137acd632ca76)) +# [6.2.0-prerelease.31](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.30...@patternfly/react-core@6.2.0-prerelease.31) (2025-03-11) +### Bug Fixes -## 4.168.10 (2021-10-29) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.19 ([#11642](https://github.com/patternfly/patternfly-react/issues/11642)) ([420232c](https://github.com/patternfly/patternfly-react/commit/420232c5172a26c7921ac43469c8910d31c932b2)) +# [6.2.0-prerelease.30](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.29...@patternfly/react-core@6.2.0-prerelease.30) (2025-03-10) ### Bug Fixes -* **Banner:** forward props ([#6511](https://github.com/patternfly/patternfly-react/issues/6511)) ([e36c890](https://github.com/patternfly/patternfly-react/commit/e36c89077afa82340994c0e3c0fc929e601e01bc)) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.16 ([#11629](https://github.com/patternfly/patternfly-react/issues/11629)) ([920e709](https://github.com/patternfly/patternfly-react/commit/920e70953ee536cadeb2604e1f323d6d0e71451c)) + +# [6.2.0-prerelease.29](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.28...@patternfly/react-core@6.2.0-prerelease.29) (2025-03-10) +### Bug Fixes +- **MenuItem:** mouse can trigger tooltip on aria-disabled items ([#11567](https://github.com/patternfly/patternfly-react/issues/11567)) ([b4c0781](https://github.com/patternfly/patternfly-react/commit/b4c07813fc334427bc313ab0ca0d8c6f3fecc1f6)) +# [6.2.0-prerelease.28](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.27...@patternfly/react-core@6.2.0-prerelease.28) (2025-03-06) +### Bug Fixes -## 4.168.9 (2021-10-28) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.15 ([#11615](https://github.com/patternfly/patternfly-react/issues/11615)) ([49f3f70](https://github.com/patternfly/patternfly-react/commit/49f3f70f44717f156df542c2d6b9facad1caeff4)) -**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.27](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.26...@patternfly/react-core@6.2.0-prerelease.27) (2025-03-05) +### Bug Fixes +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.14 ([#11609](https://github.com/patternfly/patternfly-react/issues/11609)) ([f8af65a](https://github.com/patternfly/patternfly-react/commit/f8af65a09409331bfea6c5818c333457b35fe84b)) +# [6.2.0-prerelease.26](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.25...@patternfly/react-core@6.2.0-prerelease.26) (2025-03-04) +**Note:** Version bump only for package @patternfly/react-core -## 4.168.8 (2021-10-27) +# [6.2.0-prerelease.25](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.24...@patternfly/react-core@6.2.0-prerelease.25) (2025-03-03) **Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.24](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.23...@patternfly/react-core@6.2.0-prerelease.24) (2025-02-27) +### Bug Fixes +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.11 ([#11565](https://github.com/patternfly/patternfly-react/issues/11565)) ([f8832f1](https://github.com/patternfly/patternfly-react/commit/f8832f1b5abd0b62c61905eaeea0584daeb0a650)) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.12 ([#11571](https://github.com/patternfly/patternfly-react/issues/11571)) ([df1322d](https://github.com/patternfly/patternfly-react/commit/df1322d1550f8a83a227534a670547895457d959)) +# [6.2.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.22...@patternfly/react-core@6.2.0-prerelease.23) (2025-02-25) -## 4.168.7 (2021-10-27) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.21...@patternfly/react-core@6.2.0-prerelease.22) (2025-02-24) ### Bug Fixes -* change transformer cjs package to private ([#6515](https://github.com/patternfly/patternfly-react/issues/6515)) ([efcb357](https://github.com/patternfly/patternfly-react/commit/efcb3573b71541328ce2b16caa80ce33b2a62131)) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.9 ([#11550](https://github.com/patternfly/patternfly-react/issues/11550)) ([e4c7d8d](https://github.com/patternfly/patternfly-react/commit/e4c7d8d3cdf474c9e477091c0867dccbdd17d1f7)) +# [6.2.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.20...@patternfly/react-core@6.2.0-prerelease.21) (2025-02-24) +### Bug Fixes +- **DescriptionList:** allow help text button popover to open via keyboard ([#11546](https://github.com/patternfly/patternfly-react/issues/11546)) ([4250f67](https://github.com/patternfly/patternfly-react/commit/4250f67332bbf975b22d5371fd8bf66eea8c2fe0)) +### Features -## 4.168.6 (2021-10-26) +- **Label:** allow isClickable to be set manually ([#11549](https://github.com/patternfly/patternfly-react/issues/11549)) ([a0100a0](https://github.com/patternfly/patternfly-react/commit/a0100a05b2729da8fb6922367d8ae8291b219149)) -**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.19...@patternfly/react-core@6.2.0-prerelease.20) (2025-02-20) +### Bug Fixes +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.7 ([#11543](https://github.com/patternfly/patternfly-react/issues/11543)) ([1779da2](https://github.com/patternfly/patternfly-react/commit/1779da23c863dfc7637ad68d3e266253d77569e9)) +- **FileUpload:** hid input of type file from AT ([#11438](https://github.com/patternfly/patternfly-react/issues/11438)) ([9b41c4f](https://github.com/patternfly/patternfly-react/commit/9b41c4fcc72b3ade937dddf144bb387b9866cb95)) +- **SearchInput:** allowed spreading of props to input element ([#11540](https://github.com/patternfly/patternfly-react/issues/11540)) ([1c787a8](https://github.com/patternfly/patternfly-react/commit/1c787a8122e6e125c1bf4bb30793245856edf383)) +# [6.2.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.18...@patternfly/react-core@6.2.0-prerelease.19) (2025-02-14) +### Bug Fixes -## 4.168.5 (2021-10-26) +- **deps:** update dependency @patternfly/patternfly to v6.2.0-prerelease.4 ([#11525](https://github.com/patternfly/patternfly-react/issues/11525)) ([04daac6](https://github.com/patternfly/patternfly-react/commit/04daac6234bf7b85bdf663e4e9cb1093a16b9f44)) +# [6.2.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.17...@patternfly/react-core@6.2.0-prerelease.18) (2025-02-13) ### Bug Fixes -* **tokens:** added check for no matching var to avoid infinite loop ([#6502](https://github.com/patternfly/patternfly-react/issues/6502)) ([99605c2](https://github.com/patternfly/patternfly-react/commit/99605c213f12490d0abe75910e05c3e6da26a1f3)) +- **SearchInput:** advanced search aria-expanded set by default ([#11494](https://github.com/patternfly/patternfly-react/issues/11494)) ([64842c0](https://github.com/patternfly/patternfly-react/commit/64842c08b8816f528782601d8f16668a2e364504)) +# [6.2.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.16...@patternfly/react-core@6.2.0-prerelease.17) (2025-02-12) +**Note:** Version bump only for package @patternfly/react-core + +# [6.2.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.15...@patternfly/react-core@6.2.0-prerelease.16) (2025-02-12) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.14...@patternfly/react-core@6.2.0-prerelease.15) (2025-01-28) -## 4.168.4 (2021-10-26) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.13...@patternfly/react-core@6.2.0-prerelease.14) (2025-01-28) ### Bug Fixes -* add transformer package ([#6507](https://github.com/patternfly/patternfly-react/issues/6507)) ([daffd28](https://github.com/patternfly/patternfly-react/commit/daffd2864388abe63e625f962a8b38c2b7056209)) +- **Button:** updated rendering of aria-disabled attribute ([#11478](https://github.com/patternfly/patternfly-react/issues/11478)) ([058b14f](https://github.com/patternfly/patternfly-react/commit/058b14fc93233860cd604cdfb60f7c666cc0d436)) +# [6.2.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.12...@patternfly/react-core@6.2.0-prerelease.13) (2025-01-27) +### Bug Fixes + +- **TextArea:** added missing modifier class ([#11482](https://github.com/patternfly/patternfly-react/issues/11482)) ([cba24a1](https://github.com/patternfly/patternfly-react/commit/cba24a1eda8cf789692be158e2bdcf1a174c7ece)) +# [6.2.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.11...@patternfly/react-core@6.2.0-prerelease.12) (2025-01-27) +### Features -## 4.168.3 (2021-10-26) +- **JumpLinks:** Add replaceNavHistory option ([#11473](https://github.com/patternfly/patternfly-react/issues/11473)) ([8594b4c](https://github.com/patternfly/patternfly-react/commit/8594b4c15b044d8abdaf5c5af82ec85cc18701cb)) +# [6.2.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.10...@patternfly/react-core@6.2.0-prerelease.11) (2025-01-24) ### Bug Fixes -* **transformer:** publish transformer in patternfly org ([#6506](https://github.com/patternfly/patternfly-react/issues/6506)) ([b739af3](https://github.com/patternfly/patternfly-react/commit/b739af318400b41d4e9a53bdff6232ecc176916e)) +- **FileUploadField:** Allow browse button disable ([#11476](https://github.com/patternfly/patternfly-react/issues/11476)) ([0d31dcd](https://github.com/patternfly/patternfly-react/commit/0d31dcd160f74e3d0018a588730157303a2323a9)) +- **Truncate:** fix text duplication in middle position ([#11417](https://github.com/patternfly/patternfly-react/issues/11417)) ([711a561](https://github.com/patternfly/patternfly-react/commit/711a56192d8dcfd754439b6aff86ea733e42e7d0)) +# [6.2.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.9...@patternfly/react-core@6.2.0-prerelease.10) (2025-01-24) +### Bug Fixes +- **ClipboardCopy:** Add string[] type to children ([#11177](https://github.com/patternfly/patternfly-react/issues/11177)) ([33feb10](https://github.com/patternfly/patternfly-react/commit/33feb109b2b95bce52c8b91a46494257b46e0a3d)) +# [6.2.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.8...@patternfly/react-core@6.2.0-prerelease.9) (2025-01-23) -## 4.168.2 (2021-10-26) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.7...@patternfly/react-core@6.2.0-prerelease.8) (2025-01-23) ### Bug Fixes -* **readme:** update react-core readme ([#6505](https://github.com/patternfly/patternfly-react/issues/6505)) ([d4f9a11](https://github.com/patternfly/patternfly-react/commit/d4f9a114584eea7ab67873f199e80b348886e14b)) - - +- **deps:** update dependency focus-trap to v7.6.4 ([#11444](https://github.com/patternfly/patternfly-react/issues/11444)) ([c32cece](https://github.com/patternfly/patternfly-react/commit/c32ceceb0d7d3380732c17bf79350428444d48b4)) +# [6.2.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.6...@patternfly/react-core@6.2.0-prerelease.7) (2025-01-21) +### Bug Fixes -## 4.168.1 (2021-10-26) +- **deps:** update dependency @patternfly/patternfly to v6.1.0 ([#11436](https://github.com/patternfly/patternfly-react/issues/11436)) ([b1b172d](https://github.com/patternfly/patternfly-react/commit/b1b172dc1b427ce8883ec1078c307955bc60a2eb)) +# [6.2.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.5...@patternfly/react-core@6.2.0-prerelease.6) (2025-01-20) ### Bug Fixes -* **DualListSelector:** account for duplicate folders ([#6499](https://github.com/patternfly/patternfly-react/issues/6499)) ([e531e68](https://github.com/patternfly/patternfly-react/commit/e531e68e7adc58459b3630f5c915ed69e3021012)) +- **Toolbar:** Fix formatting of Stacked example ([#11426](https://github.com/patternfly/patternfly-react/issues/11426)) ([ffc6d88](https://github.com/patternfly/patternfly-react/commit/ffc6d883aa4ce3c23403e905a41f4f3e6ecd8d59)) +# [6.2.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.4...@patternfly/react-core@6.2.0-prerelease.5) (2025-01-20) +### Features +- **Table,misc:** rewrite column management demo, remove old dnd examples ([#11295](https://github.com/patternfly/patternfly-react/issues/11295)) ([b24648d](https://github.com/patternfly/patternfly-react/commit/b24648d5b2d515691032798ceecd6b6fc63d63e5)) +# [6.2.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.3...@patternfly/react-core@6.2.0-prerelease.4) (2025-01-14) -# 4.168.0 (2021-10-26) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.2...@patternfly/react-core@6.2.0-prerelease.3) (2025-01-14) ### Features -* **toolbar:** add sticky top modifier to toolbar ([#6447](https://github.com/patternfly/patternfly-react/issues/6447)) ([fe7605a](https://github.com/patternfly/patternfly-react/commit/fe7605a67428b43ec00b3cb2117270296576737c)) +- **Text area:** Add resize disable feature ([#11383](https://github.com/patternfly/patternfly-react/issues/11383)) ([9868ab5](https://github.com/patternfly/patternfly-react/commit/9868ab5364b6776b3782c8a0fb5cfa8b7581e9f0)) +# [6.2.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.1...@patternfly/react-core@6.2.0-prerelease.2) (2025-01-10) + +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.2.0-prerelease.0...@patternfly/react-core@6.2.0-prerelease.1) (2025-01-10) +**Note:** Version bump only for package @patternfly/react-core +# [6.2.0-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.1-prerelease.2...@patternfly/react-core@6.2.0-prerelease.0) (2025-01-06) -## 4.167.1 (2021-10-26) +**Note:** Version bump only for package @patternfly/react-core +## [6.1.1-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.1-prerelease.1...@patternfly/react-core@6.1.1-prerelease.2) (2025-01-06) ### Bug Fixes -* **types:** SelectOptionProp made optional ([#6503](https://github.com/patternfly/patternfly-react/issues/6503)) ([716ac80](https://github.com/patternfly/patternfly-react/commit/716ac80e2414507d589ee3002fc0cea0068ae59c)) +- **FileUpload:** remove empty icon from example ([#11359](https://github.com/patternfly/patternfly-react/issues/11359)) ([bcc2f8c](https://github.com/patternfly/patternfly-react/commit/bcc2f8c9077ed4def6f8051f824d3fdc12078c8b)) +## [6.1.1-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.1-prerelease.0...@patternfly/react-core@6.1.1-prerelease.1) (2024-12-19) +### Bug Fixes +- **DualListSelector:** Resolve tsc type issues in PF6 ([#11360](https://github.com/patternfly/patternfly-react/issues/11360)) ([6a1686f](https://github.com/patternfly/patternfly-react/commit/6a1686f55f2148248c6e6ecf2a92e04d9c70af5b)) +- replace react useId with lodash uniqueId ([#11351](https://github.com/patternfly/patternfly-react/issues/11351)) ([#11357](https://github.com/patternfly/patternfly-react/issues/11357)) ([1c3dd97](https://github.com/patternfly/patternfly-react/commit/1c3dd97e5a7da813023de1e6d584008c59efd7fd)) +## [6.1.1-prerelease.0](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0...@patternfly/react-core@6.1.1-prerelease.0) (2024-12-18) -# 4.167.0 (2021-10-26) +**Note:** Version bump only for package @patternfly/react-core +# 6.1.0 (2024-12-16) -### Features +### Bug Fixes -* **TextInputGroup:** add text input group ([#6482](https://github.com/patternfly/patternfly-react/issues/6482)) ([a02fd4f](https://github.com/patternfly/patternfly-react/commit/a02fd4fe3345245b2252ee5a261f5b1460490642)), closes [patternfly/patternfly-react#6409](https://github.com/patternfly/patternfly-react/issues/6409) +- Update promote.sh to release 6.1.0 ([2b5106f](https://github.com/patternfly/patternfly-react/commit/2b5106ff88ce207d4a9ed2066fd390009e81fb79)) +# [6.1.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.15...@patternfly/react-core@6.1.0-prerelease.16) (2024-12-13) +**Note:** Version bump only for package @patternfly/react-core +# [6.1.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.14...@patternfly/react-core@6.1.0-prerelease.15) (2024-12-10) +### Bug Fixes -## 4.166.4 (2021-10-26) +- **CalendarMonth:** fix selection closing datepicker popover ([#11341](https://github.com/patternfly/patternfly-react/issues/11341)) ([d8c26ac](https://github.com/patternfly/patternfly-react/commit/d8c26acdf5a50e16fc84e23371b37c74baaa95c9)) +### Features -### Bug Fixes +- **Wizard:** replace deprecations in examples ([#11298](https://github.com/patternfly/patternfly-react/issues/11298)) ([2de9fea](https://github.com/patternfly/patternfly-react/commit/2de9feaaf661307f23991b5c51d786e1106db114)) -* **KebabToggle:** adds event to onToggle definition ([#6490](https://github.com/patternfly/patternfly-react/issues/6490)) ([0441575](https://github.com/patternfly/patternfly-react/commit/04415757917062aa13c06b34bd94ef38c2334088)) +# [6.1.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.13...@patternfly/react-core@6.1.0-prerelease.14) (2024-12-04) +### Bug Fixes +- **expandable section:** Remove returns within text content so that example truncates correctly ([#11226](https://github.com/patternfly/patternfly-react/issues/11226)) ([5b91445](https://github.com/patternfly/patternfly-react/commit/5b914458c01a13abc782af85a8d85e002f59f37e)) +# [6.1.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.12...@patternfly/react-core@6.1.0-prerelease.13) (2024-12-02) +### Features -## 4.166.3 (2021-10-26) +- **FileUpload:** expose dropdown error types ([#11289](https://github.com/patternfly/patternfly-react/issues/11289)) ([469ea9d](https://github.com/patternfly/patternfly-react/commit/469ea9d75ff00ccaba2112937ed89ee0b8a1bb7f)) +# [6.1.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.11...@patternfly/react-core@6.1.0-prerelease.12) (2024-12-02) ### Bug Fixes -* **Modal:** test clean up ([#6489](https://github.com/patternfly/patternfly-react/issues/6489)) ([c8eaa7c](https://github.com/patternfly/patternfly-react/commit/c8eaa7c838fbedb98ea0f38e4f535488040a72e2)) +- **docs:** drilldown infinite loop ([#11271](https://github.com/patternfly/patternfly-react/issues/11271)) ([c6f9df9](https://github.com/patternfly/patternfly-react/commit/c6f9df91572041b8ea3b7d1e13cdcf7cac38715d)) +# [6.1.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.10...@patternfly/react-core@6.1.0-prerelease.11) (2024-11-25) +**Note:** Version bump only for package @patternfly/react-core +# [6.1.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.9...@patternfly/react-core@6.1.0-prerelease.10) (2024-11-20) +### Bug Fixes -## 4.166.2 (2021-10-25) +- **Toolbar:** Fixed null exception in Toolbar filter ([#11227](https://github.com/patternfly/patternfly-react/issues/11227)) ([76b516e](https://github.com/patternfly/patternfly-react/commit/76b516ed1e69a390c4b97761df9441bdd8b288fd)) -**Note:** Version bump only for package @patternfly/react-core +# [6.1.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.8...@patternfly/react-core@6.1.0-prerelease.9) (2024-11-20) +### Bug Fixes +- **deps:** update dependency react-dropzone to v14.3.5 (main) ([#11152](https://github.com/patternfly/patternfly-react/issues/11152)) ([849b347](https://github.com/patternfly/patternfly-react/commit/849b3477cf080fcc047f21824ab742b58dcd81e8)) +### Features +- **docs:** add draggable demos to component pages ([#11112](https://github.com/patternfly/patternfly-react/issues/11112)) ([dee6247](https://github.com/patternfly/patternfly-react/commit/dee6247762e17d6a53a7cb480ace9927d016a63b)) +- **Select/Dropdown/MenuContainer:** arrow key handling to focus items ([#11132](https://github.com/patternfly/patternfly-react/issues/11132)) ([ffb3841](https://github.com/patternfly/patternfly-react/commit/ffb3841016ffd8cb320cf56d345559c17caf2498)) -## 4.166.1 (2021-10-25) +# [6.1.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.7...@patternfly/react-core@6.1.0-prerelease.8) (2024-11-20) **Note:** Version bump only for package @patternfly/react-core +# [6.1.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.6...@patternfly/react-core@6.1.0-prerelease.7) (2024-11-19) +### Bug Fixes +- **Modal:** Fixes various bugs in the Modal and deprecated Modal ([#11207](https://github.com/patternfly/patternfly-react/issues/11207)) ([2fd40f3](https://github.com/patternfly/patternfly-react/commit/2fd40f3e5527eb4ac76b5edbb1b4962007ad24cf)) +# [6.1.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.5...@patternfly/react-core@6.1.0-prerelease.6) (2024-11-19) -# 4.166.0 (2021-10-25) - - -### Features - -* **Tabs:** Added support for tab content body with padding, added tabs open and tab secondary tabs demos ([#6484](https://github.com/patternfly/patternfly-react/issues/6484)) ([0ccbe9d](https://github.com/patternfly/patternfly-react/commit/0ccbe9d1e6e0dac0730466c92a90fe2cd9f6560d)) +### Bug Fixes +- **CheckboxReversed example:** fix prop ([#11175](https://github.com/patternfly/patternfly-react/issues/11175)) ([47cb1de](https://github.com/patternfly/patternfly-react/commit/47cb1de593ab6dc39e207786e817eb97805427df)) +- **split/stack:** add component prop to StackItem/SplitItem ([#11170](https://github.com/patternfly/patternfly-react/issues/11170)) ([a6e0821](https://github.com/patternfly/patternfly-react/commit/a6e08212c4a3e6a88f41b91abaa1faa196631e81)) +# [6.1.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.4...@patternfly/react-core@6.1.0-prerelease.5) (2024-11-18) +### Bug Fixes +- **deps:** update dependency focus-trap to v7.6.2 ([#11219](https://github.com/patternfly/patternfly-react/issues/11219)) ([d6fa6b4](https://github.com/patternfly/patternfly-react/commit/d6fa6b467c5612ff0abef72110075693aa8fbbef)) +- **deps:** update dependency tslib to ^2.8.1 ([#11222](https://github.com/patternfly/patternfly-react/issues/11222)) ([7c90e9b](https://github.com/patternfly/patternfly-react/commit/7c90e9bff23083f097e78246570be60dacfb27c0)) -## 4.165.1 (2021-10-21) +# [6.1.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.3...@patternfly/react-core@6.1.0-prerelease.4) (2024-11-15) **Note:** Version bump only for package @patternfly/react-core +# [6.1.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.2...@patternfly/react-core@6.1.0-prerelease.3) (2024-11-14) +### Bug Fixes +- **deps:** update dependency focus-trap to v7.6.1 ([#11180](https://github.com/patternfly/patternfly-react/issues/11180)) ([56411eb](https://github.com/patternfly/patternfly-react/commit/56411eb479257c5e0f354270f36841367ba244e8)) +# [6.1.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.1...@patternfly/react-core@6.1.0-prerelease.2) (2024-11-13) -# 4.165.0 (2021-10-21) +### Bug Fixes +- **CodeEditor:** Set default height ([#11014](https://github.com/patternfly/patternfly-react/issues/11014)) ([6ddfc93](https://github.com/patternfly/patternfly-react/commit/6ddfc93376a48028fed46948b08a185e3c9617f6)) +- **MenuToggle:** incorrect inheritance of HTMLInputElement ([#11145](https://github.com/patternfly/patternfly-react/issues/11145)) ([838d64a](https://github.com/patternfly/patternfly-react/commit/838d64ab66231e8c5d28a850fbc54f67bcb78aa2)) -### Features +# [6.1.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.1.0-prerelease.0...@patternfly/react-core@6.1.0-prerelease.1) (2024-10-30) -* **label:** added compact label, updated horizontal grid card demo ([#6448](https://github.com/patternfly/patternfly-react/issues/6448)) ([89e0431](https://github.com/patternfly/patternfly-react/commit/89e04317924282140606d45f2292aa3f658b4b6c)) +### Bug Fixes +- **DualListSelector example:** improved behaviour when filter is applied ([#11097](https://github.com/patternfly/patternfly-react/issues/11097)) ([b146983](https://github.com/patternfly/patternfly-react/commit/b146983291454cd64099e9a10a2ccb6ad249a920)) +# 6.1.0-prerelease.0 (2024-10-24) +**Note:** Version bump only for package @patternfly/react-core +# 6.0.0 (2024-10-24) -## 4.164.1 (2021-10-21) +**Note:** Version bump only for package @patternfly/react-core +# [6.0.0-prerelease.23](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.22...@patternfly/react-core@6.0.0-prerelease.23) (2024-10-23) ### Bug Fixes -* **DescriptionListGroup:** forward props to DOM ([#6466](https://github.com/patternfly/patternfly-react/issues/6466)) ([b78e2aa](https://github.com/patternfly/patternfly-react/commit/b78e2aa9c0360ce8418f6e7b55274ea1a50de518)) +- **Menus:** added new fix for scroll jump bug ([#11119](https://github.com/patternfly/patternfly-react/issues/11119)) ([f19a7a5](https://github.com/patternfly/patternfly-react/commit/f19a7a51be930da22a1067c48d0a5c0185a345e4)) +# [6.0.0-prerelease.22](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.21...@patternfly/react-core@6.0.0-prerelease.22) (2024-10-23) + +### Bug Fixes +- **Select/Dropdown:** updated autofocus to false by default in v6 ([#11115](https://github.com/patternfly/patternfly-react/issues/11115)) ([2b2bc35](https://github.com/patternfly/patternfly-react/commit/2b2bc35d3da32c662050645838a903bf479d58fc)) +# [6.0.0-prerelease.21](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.20...@patternfly/react-core@6.0.0-prerelease.21) (2024-10-02) +### Bug Fixes -# 4.164.0 (2021-10-20) +- **Menu toggle:** Remove pf-m-action modifier ([#11096](https://github.com/patternfly/patternfly-react/issues/11096)) ([fe6871c](https://github.com/patternfly/patternfly-react/commit/fe6871cf3063eab33dc572f30a57c52e84f34131)) +- **Page:** Remove drawer content body wrapper from notification drawer ([#11094](https://github.com/patternfly/patternfly-react/issues/11094)) ([ce25e4c](https://github.com/patternfly/patternfly-react/commit/ce25e4ce2d687ad0ae818d575f69ef9070a6ca4a)) +# [6.0.0-prerelease.20](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.19...@patternfly/react-core@6.0.0-prerelease.20) (2024-09-30) ### Features -* **Progress:** allow node titles ([#6470](https://github.com/patternfly/patternfly-react/issues/6470)) ([46d5252](https://github.com/patternfly/patternfly-react/commit/46d52523ad5111bb11729c2750abe9aeb35d9326)) - +- **charts:** import charts from @patternfly/react-charts/victory ([#11091](https://github.com/patternfly/patternfly-react/issues/11091)) ([2d3921b](https://github.com/patternfly/patternfly-react/commit/2d3921b7dab1733fce0a640e7d64d01fc21dbac1)) +# [6.0.0-prerelease.19](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.18...@patternfly/react-core@6.0.0-prerelease.19) (2024-09-26) +**Note:** Version bump only for package @patternfly/react-core +# [6.0.0-prerelease.18](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.17...@patternfly/react-core@6.0.0-prerelease.18) (2024-09-26) -# 4.163.0 (2021-10-20) +### Bug Fixes +- **datalist:** actions wrapper ([#10939](https://github.com/patternfly/patternfly-react/issues/10939)) ([833465f](https://github.com/patternfly/patternfly-react/commit/833465f0ea0ef48cd3a02e307c0dd559a8f4e880)) ### Features -* **DualListSelector:** add disabled flag ([#6442](https://github.com/patternfly/patternfly-react/issues/6442)) ([85e1314](https://github.com/patternfly/patternfly-react/commit/85e131435be12c2df79336e9fa56987ed3717417)) - +- **Tile:** deprecate ([#10821](https://github.com/patternfly/patternfly-react/issues/10821)) ([548cd34](https://github.com/patternfly/patternfly-react/commit/548cd34748d8c3c0e022d9b8dd275e628c5828f3)) +# [6.0.0-prerelease.17](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.16...@patternfly/react-core@6.0.0-prerelease.17) (2024-09-24) +### Bug Fixes +- **Modal:** Allow users to add classes to backdrop ([#11015](https://github.com/patternfly/patternfly-react/issues/11015)) ([f6f8abb](https://github.com/patternfly/patternfly-react/commit/f6f8abb8f1a464a78754580f47f5685de03927fd)) -## 4.162.8 (2021-10-20) +# [6.0.0-prerelease.16](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.15...@patternfly/react-core@6.0.0-prerelease.16) (2024-09-24) **Note:** Version bump only for package @patternfly/react-core +# [6.0.0-prerelease.15](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.14...@patternfly/react-core@6.0.0-prerelease.15) (2024-09-23) + +### Bug Fixes +- **table:** update v5 to v6 for docs, description list, draggable, Th ([#10968](https://github.com/patternfly/patternfly-react/issues/10968)) ([db72b52](https://github.com/patternfly/patternfly-react/commit/db72b5287c18d023c094be247a46f9352d50fd7b)) +### Features +- **DataList:** use Checkbox in DataListCheck ([#10916](https://github.com/patternfly/patternfly-react/issues/10916)) ([bd61a94](https://github.com/patternfly/patternfly-react/commit/bd61a9423fbe8ef41072ce993b5d0ea8dfbd7080)) -## 4.162.7 (2021-10-20) +# [6.0.0-prerelease.14](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.13...@patternfly/react-core@6.0.0-prerelease.14) (2024-09-20) **Note:** Version bump only for package @patternfly/react-core +# [6.0.0-prerelease.13](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.12...@patternfly/react-core@6.0.0-prerelease.13) (2024-09-19) +### Bug Fixes +- **Modal:** Prevent auto aria-labelledby if aria-label is passed ([#11012](https://github.com/patternfly/patternfly-react/issues/11012)) ([5bb4c1f](https://github.com/patternfly/patternfly-react/commit/5bb4c1fb500315b85c54c22b79846f90805cfd5d)) +# [6.0.0-prerelease.12](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.11...@patternfly/react-core@6.0.0-prerelease.12) (2024-09-18) -## [4.162.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@4.162.5...@patternfly/react-core@4.162.6) (2021-10-18) +### Bug Fixes -**Note:** Version bump only for package @patternfly/react-core +- **generate tokens:** prefix tokens with a t\_ ([#11002](https://github.com/patternfly/patternfly-react/issues/11002)) ([0dac6b8](https://github.com/patternfly/patternfly-react/commit/0dac6b88b9f560975627c80c6e8ab816d8b78ac9)) +# [6.0.0-prerelease.11](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.10...@patternfly/react-core@6.0.0-prerelease.11) (2024-09-17) +### Bug Fixes +- **empty state:** Do not require titleText prop) ([#10987](https://github.com/patternfly/patternfly-react/issues/10987)) ([c7f037a](https://github.com/patternfly/patternfly-react/commit/c7f037ac57b58b6955631f4130466bbcfdaecfba)) +# [6.0.0-prerelease.10](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.9...@patternfly/react-core@6.0.0-prerelease.10) (2024-09-16) -## [4.162.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@4.162.4...@patternfly/react-core@4.162.5) (2021-10-14) +**Note:** Version bump only for package @patternfly/react-core +# [6.0.0-prerelease.9](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.8...@patternfly/react-core@6.0.0-prerelease.9) (2024-09-13) ### Bug Fixes -* **wizard:** change wizard toggle and wizard toggle item to span tags ([#6428](https://github.com/patternfly/patternfly-react/issues/6428)) ([7b73e61](https://github.com/patternfly/patternfly-react/commit/7b73e61a26d29be8b8ebed5e87a1682600dee1e8)) - +- **tree view:** Fix with action items example so menu is closed by default ([#10947](https://github.com/patternfly/patternfly-react/issues/10947)) ([26525f0](https://github.com/patternfly/patternfly-react/commit/26525f0f2594a12f43053ab9d9cf781a464b0a04)) +# [6.0.0-prerelease.8](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.7...@patternfly/react-core@6.0.0-prerelease.8) (2024-09-13) +### Bug Fixes +- **slider:** Add tabular number font styling to tooltips ([#10901](https://github.com/patternfly/patternfly-react/issues/10901)) ([b41061c](https://github.com/patternfly/patternfly-react/commit/b41061c3b83e5f2a5e865170543a63d307ecaa17)) -## [4.162.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@4.162.3...@patternfly/react-core@4.162.4) (2021-10-14) +# [6.0.0-prerelease.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.6...@patternfly/react-core@6.0.0-prerelease.7) (2024-09-12) +### Features -### Performance Improvements +- **Content:** add editorial support ([#10881](https://github.com/patternfly/patternfly-react/issues/10881)) ([c671921](https://github.com/patternfly/patternfly-react/commit/c67192152b1e319228a99626aea735dc1505032a)) -* **TreeView:** add memoization + test demo ([#6362](https://github.com/patternfly/patternfly-react/issues/6362)) ([6e35627](https://github.com/patternfly/patternfly-react/commit/6e35627ded8d156da8898ffb6252c868504fbcd9)) +# [6.0.0-prerelease.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.5...@patternfly/react-core@6.0.0-prerelease.6) (2024-09-12) +### Bug Fixes +- **deps:** update dependency focus-trap to v7.6.0 ([#10977](https://github.com/patternfly/patternfly-react/issues/10977)) ([125a137](https://github.com/patternfly/patternfly-react/commit/125a1374b178d5b9892a2ba1ee1e89f46e3c7894)) +# [6.0.0-prerelease.5](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.4...@patternfly/react-core@6.0.0-prerelease.5) (2024-09-11) +**Note:** Version bump only for package @patternfly/react-core -## [4.162.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@4.162.2...@patternfly/react-core@4.162.3) (2021-10-13) +# [6.0.0-prerelease.4](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.3...@patternfly/react-core@6.0.0-prerelease.4) (2024-09-10) -**Note:** Version bump only for package @patternfly/react-core +### Features +- **TextInputGroup:** added validation support ([#10815](https://github.com/patternfly/patternfly-react/issues/10815)) ([4e32ef9](https://github.com/patternfly/patternfly-react/commit/4e32ef9dda84be96e8901255f09ddb27fbec1f6f)) +# [6.0.0-prerelease.3](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.2...@patternfly/react-core@6.0.0-prerelease.3) (2024-09-10) +### Bug Fixes +- **deps:** update dependency tslib to ^2.7.0 ([#10949](https://github.com/patternfly/patternfly-react/issues/10949)) ([024b3cc](https://github.com/patternfly/patternfly-react/commit/024b3cc4b1afd4ba9f2dc774c0842712d4fbab1a)) -## [4.162.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@4.162.1...@patternfly/react-core@4.162.2) (2021-10-11) +# [6.0.0-prerelease.2](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-prerelease.1...@patternfly/react-core@6.0.0-prerelease.2) (2024-09-09) -**Note:** Version bump only for package @patternfly/react-core +### Features +- **MenuToggle:** add placeholder support ([#10882](https://github.com/patternfly/patternfly-react/issues/10882)) ([dd53ab9](https://github.com/patternfly/patternfly-react/commit/dd53ab94ea49e93b590f258fe923b2653ac23e67)) +# [6.0.0-prerelease.1](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-core@6.0.0-alpha.106...@patternfly/react-core@6.0.0-prerelease.1) (2024-09-07) +### Bug Fixes +- **CI:** Update snapshot tests ([#10922](https://github.com/patternfly/patternfly-react/issues/10922)) ([e7ba60e](https://github.com/patternfly/patternfly-react/commit/e7ba60e78895e955abc5a38fe27c1c87cc1d2ee2)) +- **expandable section:** update to use ; ``` -All component documentation is available on [PatternFly.org](https://www.patternfly.org/v4/components/about-modal). +All component documentation is available on [PatternFly.org](https://www.patternfly.org/components/about-modal). #### Advanced usage -1. [Applying Overpass font](../../ADVANCED-USAGE-README.md#Applying-Overpass-font) -2. [Tree shaking](../../ADVANCED-USAGE-README.md#Tree-shaking) +1. [Applying Overpass font](https://github.com/patternfly/patternfly-react/blob/main/ADVANCED-USAGE-README.md#Applying-Overpass-font) ### Contribution guidelines -All React contributors must first be [PatternFly community contributors](https://www.patternfly.org/v4/contribute/about). If you are already a PatternFly community contributor, check out the [React contribution guidelines](https://github.com/patternfly/patternfly-react/tree/main/CONTRIBUTING.md) to make React contributions. +All React contributors must first be [PatternFly community contributors](https://www.patternfly.org/contribute/about). If you are already a PatternFly community contributor, check out the [React contribution guidelines](https://github.com/patternfly/patternfly-react/tree/main/CONTRIBUTING.md) to make React contributions. ### License PatternFly React is licensed under the [MIT License](https://github.com/patternfly/patternfly-react/tree/main/LICENSE). + diff --git a/packages/react-core/package.json b/packages/react-core/package.json index 79a41068463..0e3b9dce98c 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -1,10 +1,20 @@ { "name": "@patternfly/react-core", - "version": "4.188.0", + "version": "6.6.0-prerelease.1", "description": "This library provides a set of common React components for use with the PatternFly reference implementation.", "main": "dist/js/index.js", "module": "dist/esm/index.js", "types": "dist/esm/index.d.ts", + "typesVersions": { + "*": { + "next": [ + "dist/esm/next/index.d.ts" + ], + "deprecated": [ + "dist/esm/deprecated/index.d.ts" + ] + } + }, "patternfly:src": "src/", "sideEffects": [ "*.css", @@ -29,35 +39,28 @@ }, "homepage": "https://github.com/patternfly/patternfly-react#readme", "scripts": { - "build:umd": "rollup -c && rollup -c --environment IS_PRODUCTION", - "clean": "rimraf dist", - "generate": "node scripts/copyStyles.js" + "build:umd": "rollup -c --environment IS_PRODUCTION", + "build:single:packages": "node ../../scripts/build-single-packages.mjs --config single-packages.config.json", + "clean": "rimraf dist components layouts helpers next deprecated", + "generate": "node scripts/copyStyles.mjs", + "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json" }, "dependencies": { - "@patternfly/react-icons": "^4.39.0", - "@patternfly/react-styles": "^4.38.0", - "@patternfly/react-tokens": "^4.40.0", - "focus-trap": "6.2.2", - "react-dropzone": "9.0.0", - "tippy.js": "5.1.2", - "tslib": "^2.0.0" + "@patternfly/react-icons": "workspace:^", + "@patternfly/react-styles": "workspace:^", + "@patternfly/react-tokens": "workspace:^", + "focus-trap": "7.6.6", + "react-dropzone": "^14.3.5", + "tslib": "^2.8.1" }, "devDependencies": { - "@patternfly/patternfly": "4.166.4", - "@rollup/plugin-commonjs": "^21.0.0", - "@rollup/plugin-node-resolve": "^13.0.0", - "@rollup/plugin-replace": "^3.0.0", - "css": "^2.2.3", - "fs-extra": "^6.0.1", - "glob": "^7.1.2", - "rimraf": "^2.6.2", - "rollup": "^2.58.0", - "rollup-plugin-scss": "^3.0.0", - "rollup-plugin-terser": "^7.0.0", - "typescript": "^4.0.0" + "@patternfly/patternfly": "6.5.2", + "case-anything": "^3.1.2", + "css": "^3.0.0", + "fs-extra": "^11.3.3" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" } } diff --git a/packages/react-core/rollup.config.js b/packages/react-core/rollup.config.js deleted file mode 100644 index 1f8aeb25ac0..00000000000 --- a/packages/react-core/rollup.config.js +++ /dev/null @@ -1,7 +0,0 @@ -const { name } = require('./package.json'); -const baseConfig = require('../rollup.base'); - -module.exports = baseConfig({ - packageName: name.replace('@patternfly/', ''), - name: 'PatternFlyReact' -}); diff --git a/packages/react-core/rollup.config.mjs b/packages/react-core/rollup.config.mjs new file mode 100644 index 00000000000..0e698b71946 --- /dev/null +++ b/packages/react-core/rollup.config.mjs @@ -0,0 +1,8 @@ +// @ts-check +import baseConfig from '../rollup.base.mjs'; +import pkg from './package.json' with { type: 'json' }; + +export default baseConfig({ + packageName: pkg.name.replace('@patternfly/', ''), + name: 'PatternFlyReact' +}); diff --git a/packages/react-core/scripts/copyStyles.js b/packages/react-core/scripts/copyStyles.js deleted file mode 100644 index 8dade3b8dd0..00000000000 --- a/packages/react-core/scripts/copyStyles.js +++ /dev/null @@ -1,54 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -const { copySync, readFileSync, writeFileSync } = require('fs-extra'); -const { resolve, dirname, join } = require('path'); -const { parse: parseCSS, stringify: stringifyCSS } = require('css'); -/* eslint-enable @typescript-eslint/no-var-requires */ - -const stylesDir = resolve(__dirname, '../dist/styles'); -const pfDir = dirname(require.resolve('@patternfly/patternfly/patternfly.css')); - -const unusedSelectorRegEx = /(\.fas?|\.sr-only)/; -const unusedKeyFramesRegEx = /fa-/; -const unusedFontFamilyRegEx = /Font Awesome 5 Free/; -const ununsedFontFilesRegExt = /(fa-|\.html$|\.css$)/; - -// Copy assets -copySync(join(pfDir, 'assets/images'), join(stylesDir, 'assets/images')); -copySync(join(pfDir, 'assets/pficon'), join(stylesDir, 'assets/pficon')); -copySync(join(pfDir, 'assets/fonts'), join(stylesDir, 'assets/fonts'), { - filter(src) { - return !ununsedFontFilesRegExt.test(src); - } -}); - -// Copy css -const baseCssFiles = { - 'base.css': 'patternfly-base.css', - 'base-no-reset.css': 'patternfly-base-no-reset.css' -}; - -for (const [targetCss, baseCss] of Object.entries(baseCssFiles)) { - const css = readFileSync(join(pfDir, baseCss), 'utf8'); - const ast = parseCSS(css); - - // Core provides font awesome fonts and utlities. React does not use these - ast.stylesheet.rules = ast.stylesheet.rules.filter(rule => { - switch (rule.type) { - case 'rule': - return !rule.selectors.some(sel => unusedSelectorRegEx.test(sel)); - case 'keyframes': - return !unusedKeyFramesRegEx.test(rule.name); - case 'charset': - case 'comment': - return false; - case 'font-face': - // eslint-disable-next-line no-case-declarations - const fontFamilyDecl = rule.declarations.find(decl => decl.property === 'font-family'); - return !unusedFontFamilyRegEx.test(fontFamilyDecl.value); - default: - return true; - } - }); - - writeFileSync(join(stylesDir, targetCss), stringifyCSS(ast)); -} diff --git a/packages/react-core/scripts/copyStyles.mjs b/packages/react-core/scripts/copyStyles.mjs new file mode 100644 index 00000000000..191045303c9 --- /dev/null +++ b/packages/react-core/scripts/copyStyles.mjs @@ -0,0 +1,55 @@ +import { copySync } from 'fs-extra/esm'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { resolve, dirname, join } from 'node:path'; +import { parse as parseCSS, stringify as stringifyCSS } from 'css'; + +const require = createRequire(import.meta.url); +const stylesDir = resolve(import.meta.dirname, '../dist/styles'); +const pfDir = dirname(require.resolve('@patternfly/patternfly/patternfly.css')); + +const unusedSelectorRegEx = /(\.fas?|\.sr-only)/; +const unusedKeyFramesRegEx = /fa-/; +const unusedFontFamilyRegEx = /Font Awesome 5 Free/; +const ununsedFontFilesRegExt = /(fa-|\.html$|\.css$)/; + +// Copy assets +copySync(join(pfDir, 'assets/images'), join(stylesDir, 'assets/images')); +copySync(join(pfDir, 'assets/pficon'), join(stylesDir, 'assets/pficon')); +copySync(join(pfDir, 'assets/fonts'), join(stylesDir, 'assets/fonts'), { + filter(src) { + return !ununsedFontFilesRegExt.test(src); + } +}); + +// Copy css +const baseCssFiles = { + 'base.css': 'patternfly-base.css', + 'base-no-reset.css': 'patternfly-base-no-globals.css' +}; + +for (const [targetCss, baseCss] of Object.entries(baseCssFiles)) { + const css = readFileSync(join(pfDir, baseCss), 'utf8'); + const ast = parseCSS(css); + + // Core provides font awesome fonts and utlities. React does not use these + ast.stylesheet.rules = ast.stylesheet.rules.filter((rule) => { + switch (rule.type) { + case 'rule': + return !rule.selectors.some((sel) => unusedSelectorRegEx.test(sel)); + case 'keyframes': + return !unusedKeyFramesRegEx.test(rule.name); + case 'charset': + case 'comment': + return false; + case 'font-face': + // eslint-disable-next-line no-case-declarations + const fontFamilyDecl = rule.declarations.find((decl) => decl.property === 'font-family'); + return !unusedFontFamilyRegEx.test(fontFamilyDecl.value); + default: + return true; + } + }); + + writeFileSync(join(stylesDir, targetCss), stringifyCSS(ast)); +} diff --git a/packages/react-core/single-packages.config.json b/packages/react-core/single-packages.config.json new file mode 100644 index 00000000000..da7e08727fc --- /dev/null +++ b/packages/react-core/single-packages.config.json @@ -0,0 +1,5 @@ +{ + "packageName": "@patternfly/react-core", + "moduleGlob": ["/dist/esm/helpers/**/*.js", "/dist/esm/styles/**/index.js", "/dist/esm/*/*/**/index.js"], + "exclude": ["/dist/esm/helpers/Popper/thirdparty", "/dist/esm/next"] +} diff --git a/packages/react-core/src/components/AboutModal/AboutModal.tsx b/packages/react-core/src/components/AboutModal/AboutModal.tsx index bdf32b061af..56c0aeb93c7 100644 --- a/packages/react-core/src/components/AboutModal/AboutModal.tsx +++ b/packages/react-core/src/components/AboutModal/AboutModal.tsx @@ -1,21 +1,22 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Backdrop/backdrop'; -import { canUseDOM } from '../../helpers'; -import { KEY_CODES } from '../../helpers/constants'; -import { AboutModalContainer } from './AboutModalContainer'; -import { PickOptional } from '../../helpers/typeUtils'; - -export interface AboutModalProps { - /** Content rendered inside the about modal */ +import backgroundImage from '@patternfly/react-tokens/dist/esm/c_about_modal_box_BackgroundImage'; +import { AboutModalBoxContent } from './AboutModalBoxContent'; +import { AboutModalBoxHeader } from './AboutModalBoxHeader'; +import { AboutModalBoxBrand } from './AboutModalBoxBrand'; +import { AboutModalBoxCloseButton } from './AboutModalBoxCloseButton'; +import { AboutModalBox } from './AboutModalBox'; +import { Modal, ModalVariant } from '../Modal'; +import { useSSRSafeId } from '../../helpers'; + +export interface AboutModalProps extends React.HTMLProps { + /** Content rendered inside the about modal */ children: React.ReactNode; - /** Additional classes added to the about modal */ + /** Additional classes added to the about modal */ className?: string; /** Flag to show the about modal */ isOpen?: boolean; /** A callback for when the close button is clicked */ - onClose?: () => void; + onClose?: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void; /** Product name */ productName?: string; /** Trademark information */ @@ -24,126 +25,79 @@ export interface AboutModalProps { brandImageSrc: string; /** The alternate text of the brand image */ brandImageAlt: string; - /** The URL of the image for the background */ + /** The URL or file path of the image for the background */ backgroundImageSrc?: string; /** Prevents the about modal from rendering content inside a container; allows for more flexible layouts */ - noAboutModalBoxContentContainer?: boolean; + hasNoContentContainer?: boolean; /** The parent container to append the modal to. Defaults to document.body */ appendTo?: HTMLElement | (() => HTMLElement); + /** Aria label for the about modal. This should be used when no productName prop is provided */ + 'aria-label'?: string; /** Set aria label to the close button */ closeButtonAriaLabel?: string; /** Flag to disable focus trap */ disableFocusTrap?: boolean; } -interface ModalState { - container: HTMLElement; -} - -export class AboutModal extends React.Component { - static displayName = 'AboutModal'; - private static currentId = 0; - private id = AboutModal.currentId++; - ariaLabelledBy = `pf-about-modal-title-${this.id}`; - ariaDescribedBy = `pf-about-modal-content-${this.id}`; - - static defaultProps: PickOptional = { - className: '', - isOpen: false, - onClose: (): any => undefined, - productName: '', - trademark: '', - backgroundImageSrc: '', - noAboutModalBoxContentContainer: false, - appendTo: null as HTMLElement - }; - - constructor(props: AboutModalProps) { - super(props); - - this.state = { - container: undefined - }; - if (props.brandImageSrc && !props.brandImageAlt) { - // eslint-disable-next-line no-console - console.error('AboutModal:', 'brandImageAlt is required when a brandImageSrc is specified'); - } - } - - handleEscKeyClick = (event: KeyboardEvent) => { - if (event.keyCode === KEY_CODES.ESCAPE_KEY && this.props.isOpen) { - this.props.onClose(); - } - }; - - toggleSiblingsFromScreenReaders = (hide: boolean) => { - const { appendTo } = this.props; - const target: HTMLElement = this.getElement(appendTo); - const bodyChildren = target.children; - for (const child of Array.from(bodyChildren)) { - if (child !== this.state.container) { - hide ? child.setAttribute('aria-hidden', '' + hide) : child.removeAttribute('aria-hidden'); - } - } - }; - - getElement = (appendTo: HTMLElement | (() => HTMLElement)) => { - if (typeof appendTo === 'function') { - return appendTo(); - } - return appendTo || document.body; - }; - - componentDidMount() { - const container = document.createElement('div'); - const target: HTMLElement = this.getElement(this.props.appendTo); - this.setState({ container }); - target.appendChild(container); - target.addEventListener('keydown', this.handleEscKeyClick, false); - - if (this.props.isOpen) { - target.classList.add(css(styles.backdropOpen)); - } else { - target.classList.remove(css(styles.backdropOpen)); - } +export const AboutModal: React.FunctionComponent = ({ + children, + className, + isOpen = false, + onClose = (_e): any => undefined, + productName, + trademark, + backgroundImageSrc, + brandImageSrc, + brandImageAlt, + hasNoContentContainer = false, + appendTo, + closeButtonAriaLabel, + 'aria-label': ariaLabel, + disableFocusTrap, + ...props +}: AboutModalProps) => { + const ariaLabelledBy = useSSRSafeId('pf-about-modal-title-'); + + if (brandImageSrc && !brandImageAlt) { + // eslint-disable-next-line no-console + console.error( + 'AboutModal:', + 'brandImageAlt is required when a brandImageSrc is specified, and should not be an empty string.' + ); } - componentDidUpdate() { - const target: HTMLElement = this.getElement(this.props.appendTo); - if (this.props.isOpen) { - target.classList.add(css(styles.backdropOpen)); - this.toggleSiblingsFromScreenReaders(true); - } else { - target.classList.remove(css(styles.backdropOpen)); - this.toggleSiblingsFromScreenReaders(false); - } + if (!productName && !ariaLabel) { + // eslint-disable-next-line no-console + console.error('AboutModal:', 'Either productName or ariaLabel is required for component to be accessible'); } - componentWillUnmount() { - const target: HTMLElement = this.getElement(this.props.appendTo); - if (this.state.container) { - target.removeChild(this.state.container); - } - target.removeEventListener('keydown', this.handleEscKeyClick, false); - target.classList.remove(css(styles.backdropOpen)); + if (!isOpen) { + return null; } - - render() { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { appendTo, ...props } = this.props; - const { container } = this.state; - - if (!canUseDOM || !container) { - return null; - } - - return ReactDOM.createPortal( - , - container - ); - } -} + return ( + + + + + {productName && } + + {children} + + + + ); +}; +AboutModal.displayName = 'AboutModal'; diff --git a/packages/react-core/src/components/AboutModal/AboutModalBox.tsx b/packages/react-core/src/components/AboutModal/AboutModalBox.tsx index 5de42d9df9d..d9ad123f792 100644 --- a/packages/react-core/src/components/AboutModal/AboutModalBox.tsx +++ b/packages/react-core/src/components/AboutModal/AboutModalBox.tsx @@ -1,20 +1,19 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/AboutModalBox/about-modal-box'; export interface AboutModalBoxProps extends React.HTMLProps { - /** content rendered inside the AboutModelBox. */ + /** Content rendered inside the about modal box */ children: React.ReactNode; - /** additional classes added to the AboutModalBox */ + /** Additional classes added to the about modal box */ className?: string; } export const AboutModalBox: React.FunctionComponent = ({ children, - className = '', + className, ...props }: AboutModalBoxProps) => ( -
    +
    {children}
    ); diff --git a/packages/react-core/src/components/AboutModal/AboutModalBoxBrand.tsx b/packages/react-core/src/components/AboutModal/AboutModalBoxBrand.tsx index 78992fd61e5..a948f7d9ab5 100644 --- a/packages/react-core/src/components/AboutModal/AboutModalBoxBrand.tsx +++ b/packages/react-core/src/components/AboutModal/AboutModalBoxBrand.tsx @@ -1,23 +1,19 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/AboutModalBox/about-modal-box'; export interface AboutModalBoxBrandProps extends React.HTMLProps { - /** additional classes added to the About Modal Brand */ - className?: string; - /** the URL of the image for the Brand. */ - src?: string; - /** the alternate text of the Brand image. */ + /** The URL of the image for the brand. */ + src: string; + /** The alternate text of the brand image. */ alt: string; } export const AboutModalBoxBrand: React.FunctionComponent = ({ - className = '', - src = '', + src, alt, ...props }: AboutModalBoxBrandProps) => ( -
    +
    {alt}
    ); diff --git a/packages/react-core/src/components/AboutModal/AboutModalBoxCloseButton.tsx b/packages/react-core/src/components/AboutModal/AboutModalBoxCloseButton.tsx index ecfc11b2423..a5f56d87188 100644 --- a/packages/react-core/src/components/AboutModal/AboutModalBoxCloseButton.tsx +++ b/packages/react-core/src/components/AboutModal/AboutModalBoxCloseButton.tsx @@ -1,28 +1,22 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/AboutModalBox/about-modal-box'; import { Button } from '../Button'; -import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; export interface AboutModalBoxCloseButtonProps extends React.HTMLProps { - /** additional classes added to the About Modal Close button */ - className?: string; /** A callback for when the close button is clicked */ - onClose?: () => void; + onClose?: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void; /** Set close button aria label */ 'aria-label'?: string; } export const AboutModalBoxCloseButton: React.FunctionComponent = ({ - className = '', - onClose = () => undefined as any, + onClose = (_e) => undefined as any, 'aria-label': ariaLabel = 'Close Dialog', ...props }: AboutModalBoxCloseButtonProps) => ( -
    - +
    +
    ); AboutModalBoxCloseButton.displayName = 'AboutModalBoxCloseButton'; diff --git a/packages/react-core/src/components/AboutModal/AboutModalBoxContent.tsx b/packages/react-core/src/components/AboutModal/AboutModalBoxContent.tsx index 254dacdd6e3..5c0dd191e74 100644 --- a/packages/react-core/src/components/AboutModal/AboutModalBoxContent.tsx +++ b/packages/react-core/src/components/AboutModal/AboutModalBoxContent.tsx @@ -1,32 +1,25 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/AboutModalBox/about-modal-box'; import contentStyles from '@patternfly/react-styles/css/components/Content/content'; export interface AboutModalBoxContentProps extends React.HTMLProps { - /** content rendered inside the AboutModalBoxContent */ + /** Content rendered inside the about modal box content */ children: React.ReactNode; - /** additional classes added to the AboutModalBoxContent */ - className?: string; - /** id to use for About Modal Box aria described by */ - id: string; - /** The Trademark info for the product */ + /** The trademark info for the product */ trademark: string; /** Prevents the about modal from rendering content inside a container; allows for more flexible layouts */ - noAboutModalBoxContentContainer?: boolean; + hasNoContentContainer?: boolean; } export const AboutModalBoxContent: React.FunctionComponent = ({ children, - className = '', trademark, - id, - noAboutModalBoxContentContainer = false, + hasNoContentContainer = false, ...props }: AboutModalBoxContentProps) => ( -
    -
    - {noAboutModalBoxContentContainer ? children :
    {children}
    } +
    +
    + {hasNoContentContainer ? children :
    {children}
    }

    {trademark}

    diff --git a/packages/react-core/src/components/AboutModal/AboutModalBoxHeader.tsx b/packages/react-core/src/components/AboutModal/AboutModalBoxHeader.tsx index 4b47aed12de..4fe01e51cee 100644 --- a/packages/react-core/src/components/AboutModal/AboutModalBoxHeader.tsx +++ b/packages/react-core/src/components/AboutModal/AboutModalBoxHeader.tsx @@ -1,24 +1,20 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/AboutModalBox/about-modal-box'; import { Title } from '../Title'; export interface AboutModalBoxHeaderProps extends React.HTMLProps { - /** additional classes added to the button */ - className?: string; - /** Name of the Product */ + /** Name of the product */ productName?: string; - /** id to used for Modal Box header */ + /** Id to use for about modal box header */ id: string; } export const AboutModalBoxHeader: React.FunctionComponent = ({ - className = '', - productName = '', + productName, id, ...props }: AboutModalBoxHeaderProps) => ( -
    +
    {productName} diff --git a/packages/react-core/src/components/AboutModal/AboutModalBoxHero.tsx b/packages/react-core/src/components/AboutModal/AboutModalBoxHero.tsx deleted file mode 100644 index 8feb19b78e8..00000000000 --- a/packages/react-core/src/components/AboutModal/AboutModalBoxHero.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/AboutModalBox/about-modal-box'; -// eslint-disable-next-line camelcase -import c_about_modal_box__hero_sm_BackgroundImage from '@patternfly/react-tokens/dist/esm/c_about_modal_box__hero_sm_BackgroundImage'; - -export interface AboutModalBoxHeroProps extends React.HTMLProps { - /** additional classes added to the About Modal Hero */ - className?: string; - /** background image data or file path */ - backgroundImageSrc?: string; -} - -export const AboutModalBoxHero: React.FunctionComponent = ({ - className, - backgroundImageSrc, - ...props -}: AboutModalBoxHeroProps) => ( -
    -); -AboutModalBoxHero.displayName = 'AboutModalBoxHero'; diff --git a/packages/react-core/src/components/AboutModal/AboutModalContainer.tsx b/packages/react-core/src/components/AboutModal/AboutModalContainer.tsx deleted file mode 100644 index 169b76f7795..00000000000 --- a/packages/react-core/src/components/AboutModal/AboutModalContainer.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/layouts/Bullseye/bullseye'; -import { FocusTrap } from '../../helpers'; - -import { AboutModalBoxContent } from './AboutModalBoxContent'; -import { AboutModalBoxHeader } from './AboutModalBoxHeader'; -import { AboutModalBoxHero } from './AboutModalBoxHero'; -import { AboutModalBoxBrand } from './AboutModalBoxBrand'; -import { AboutModalBoxCloseButton } from './AboutModalBoxCloseButton'; -import { AboutModalBox } from './AboutModalBox'; -import { Backdrop } from '../Backdrop/Backdrop'; - -export interface AboutModalContainerProps extends React.HTMLProps { - /** content rendered inside the About Modal Box Content. */ - children: React.ReactNode; - /** additional classes added to the About Modal Box */ - className?: string; - /** Flag to show the About Modal */ - isOpen?: boolean; - /** A callback for when the close button is clicked */ - onClose?: () => void; - /** Product Name */ - productName?: string; - /** Trademark information */ - trademark?: string; - /** the URL of the image for the Brand. */ - brandImageSrc: string; - /** the alternate text of the Brand image. */ - brandImageAlt: string; - /** the URL of the image for the background. */ - backgroundImageSrc?: string; - /** id to use for About Modal Box aria labeled by */ - aboutModalBoxHeaderId: string; - /** id to use for About Modal Box aria described by */ - aboutModalBoxContentId: string; - /** Set close button aria label */ - closeButtonAriaLabel?: string; - /** Flag to disable focus trap */ - disableFocusTrap?: boolean; -} - -export const AboutModalContainer: React.FunctionComponent = ({ - children, - className = '', - isOpen = false, - onClose = () => undefined, - productName = '', - trademark, - brandImageSrc, - brandImageAlt, - backgroundImageSrc, - closeButtonAriaLabel, - aboutModalBoxHeaderId, - aboutModalBoxContentId, - disableFocusTrap = false, - ...props -}: AboutModalContainerProps) => { - if (!isOpen) { - return null; - } - return ( - - - - - - {productName && } - - {children} - - - - - - ); -}; -AboutModalContainer.displayName = 'AboutModalContainer'; diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModal.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModal.test.tsx index bf4c1def0b9..5d1b01522b5 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModal.test.tsx +++ b/packages/react-core/src/components/AboutModal/__tests__/AboutModal.test.tsx @@ -1,72 +1,59 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import { shallow } from 'enzyme'; -import { AboutModal } from '../AboutModal'; -import { KEY_CODES } from '../../../helpers/constants'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; -const mockListener = jest.spyOn(ReactDOM, 'createPortal'); -jest.spyOn(document, 'createElement'); -jest.spyOn(document.body, 'addEventListener'); +import { AboutModal, AboutModalProps } from '../AboutModal'; +import { KeyTypes } from '../../../helpers'; -mockListener.mockImplementation(node => node as React.ReactPortal); - -const props = { +const props: AboutModalProps = { onClose: jest.fn(), children: 'modal content', productName: 'Product Name', trademark: 'Trademark and copyright information here', brandImageSrc: 'brandImg...', - brandImageAlt: 'Brand Image', - logoImageSrc: 'logoImg...', - logoImageAlt: 'AboutModal Logo' + brandImageAlt: 'Brand Image' }; -test('AboutModal creates a container element once for div', () => { - const view = shallow( Test About Modal ); - view.update(); - expect(document.createElement).toBeCalledWith('div'); - expect(document.createElement).toHaveBeenCalledTimes(1); -}); - -test('About Modal closes with escape', () => { - shallow( - - Test About Modal - - ); - const [event, handler] = (document.body.addEventListener as any).mock.calls[0]; - expect(event).toBe('keydown'); - handler({ keyCode: KEY_CODES.ESCAPE_KEY }); - expect(props.onClose).toBeCalled(); -}); - -test('modal does not call onClose for esc key if it is not open', () => { - shallow(); - const [event, handler] = (document.body.addEventListener as any).mock.calls[0]; - expect(event).toBe('keydown'); - handler({ keyCode: KEY_CODES.ESCAPE_KEY }); - expect(props.onClose).not.toBeCalled(); -}); - -test('Each modal is given new aria-describedby and aria-labelledby', () => { - const first = new AboutModal(props); - const second = new AboutModal(props); - expect(first.ariaLabelledBy).not.toBe(second.ariaLabelledBy); - expect(first.ariaDescribedBy).not.toBe(second.ariaDescribedBy); -}); - -test('Console error is generated when the logoImageSrc is provided without logoImageAlt', () => { - const noImgAltrops = { - onClose: jest.fn(), - children: 'modal content', - productName: 'Product Name', - trademark: 'Trademark and copyright information here', - brandImageSrc: 'brandImg...', - logoImageSrc: 'logoImg...' - }; - const myMock = jest.fn() as any; - global.console = { error: myMock } as any; - const JSAboutModal = AboutModal as any; - shallow( Test About Modal ); - expect(myMock).toBeCalled(); +describe('AboutModal', () => { + test('closes with escape', async () => { + const user = userEvent.setup(); + + render(); + + await user.type(screen.getByRole('dialog'), `{${KeyTypes.Escape}}`); + expect(props.onClose).toHaveBeenCalled(); + }); + + test('does not render the modal when isOpen is not specified', () => { + render(); + expect(screen.queryByRole('dialog')).toBeNull(); + }); + + test('Console error is generated when the logoImageSrc is provided without logoImageAlt', () => { + const noImgAltrops = { + onClose: jest.fn(), + children: 'modal content', + productName: 'Product Name', + trademark: 'Trademark and copyright information here', + brandImageSrc: 'brandImg...', + logoImageSrc: 'logoImg...' + } as any; + const myMock = jest.fn() as any; + global.console = { error: myMock } as any; + + render(Test About Modal); + expect(myMock).toHaveBeenCalled(); + }); + + test('Console error is generated when the logoImageSrc is provided without logoImageAlt', () => { + const noProductNameProps = { + onClose: jest.fn(), + children: 'modal content', + trademark: 'Trademark and copyright information here' + } as any; + const myMock = jest.fn() as any; + global.console = { error: myMock } as any; + + render(Test About Modal); + expect(myMock).toHaveBeenCalled(); + }); }); diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBox.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBox.test.tsx index 07cd9333785..89a6245289b 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBox.test.tsx +++ b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBox.test.tsx @@ -1,12 +1,7 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { AboutModalBox } from '../AboutModalBox'; test('AboutModalBox Test', () => { - const view = shallow( - - This is a AboutModalBox - - ); - expect(view).toMatchSnapshot(); + const { asFragment } = render(This is a AboutModalBox); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxBrand.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxBrand.test.tsx index 5b1624c6d1b..2e6ac73621f 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxBrand.test.tsx +++ b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxBrand.test.tsx @@ -1,8 +1,7 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { AboutModalBoxBrand } from '../AboutModalBoxBrand'; test('test About Modal Brand', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx index 674b0a9dc98..75c84237b15 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx +++ b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx @@ -1,20 +1,19 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { AboutModalBoxCloseButton } from '../AboutModalBoxCloseButton'; test('AboutModalBoxCloseButton Test', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); test('AboutModalBoxCloseButton Test onclose', () => { const onClose = jest.fn(); - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); test('AboutModalBoxCloseButton Test close button aria label', () => { const closeButtonAriaLabel = 'Klose Daylok'; - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxContent.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxContent.test.tsx index 3e41a300f70..e1a8d24b687 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxContent.test.tsx +++ b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxContent.test.tsx @@ -1,12 +1,11 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { AboutModalBoxContent } from '../AboutModalBoxContent'; test('AboutModalBoxContent Test', () => { - const view = shallow( + const { asFragment } = render( This is a AboutModalBoxContent ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxHeader.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxHeader.test.tsx index 0c7f64266a4..a3650189a94 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxHeader.test.tsx +++ b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxHeader.test.tsx @@ -1,12 +1,11 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { AboutModalBoxHeader } from '../AboutModalBoxHeader'; test('AboutModalBoxHeader Test', () => { - const view = shallow( + const { asFragment } = render( This is a AboutModalBox header ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxHero.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxHero.test.tsx deleted file mode 100644 index 17d02ed0644..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxHero.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalBoxHero } from '../AboutModalBoxHero'; - -test('test About Modal Box SHero', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalContainer.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalContainer.test.tsx deleted file mode 100644 index 08b5bd40dad..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalContainer.test.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalContainer } from '../AboutModalContainer'; - -const props = { - children: 'modal content', - productName: 'Product Name', - trademark: 'Trademark and copyright information here', - brandImageSrc: 'brandImg...', - brandImageAlt: 'Brand Image', - backgroundImageSrc: 'backgroundImageSrc...', - 'aria-labelledby': 'ariaLablledbyId', - 'aria-describedby': 'ariaDescribedById' -}; -test('About Modal Container Test simple', () => { - const view = shallow(This is ModalBox content); - expect(view).toMatchSnapshot(); -}); - -test('About Modal Container Test isOpen', () => { - const view = shallow( - - This is ModalBox content - - ); - expect(view).toMatchSnapshot(); -}); - -test('About Modal Container Test with onlose', () => { - const view = shallow( - undefined} {...props}> - This is ModalBox content - - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModal.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModal.test.tsx deleted file mode 100644 index 09c62ef813b..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModal.test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModal } from '../../AboutModal'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModal should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode
    } - className={"''"} - isOpen={false} - onClose={(): any => undefined} - productName={"''"} - trademark={"''"} - brandImageSrc={'string'} - brandImageAlt={'string'} - backgroundImageSrc={"''"} - noAboutModalBoxContentContainer={false} - appendTo={null} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBox.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBox.test.tsx deleted file mode 100644 index 2dfcdb32d4d..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBox.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalBox } from '../../AboutModalBox'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModalBox should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode
    } className={"''"} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxBrand.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxBrand.test.tsx deleted file mode 100644 index 031136d8b9a..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxBrand.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalBoxBrand } from '../../AboutModalBoxBrand'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModalBoxBrand should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxCloseButton.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxCloseButton.test.tsx deleted file mode 100644 index f609da31adb..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxCloseButton.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalBoxCloseButton } from '../../AboutModalBoxCloseButton'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModalBoxCloseButton should match snapshot (auto-generated)', () => { - const view = shallow( undefined as any} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxContent.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxContent.test.tsx deleted file mode 100644 index c6eb0e1b4fd..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxContent.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalBoxContent } from '../../AboutModalBoxContent'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModalBoxContent should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode
    } - className={"''"} - id={'string'} - trademark={'string'} - noAboutModalBoxContentContainer={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxHeader.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxHeader.test.tsx deleted file mode 100644 index 8c980d03ac8..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxHeader.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalBoxHeader } from '../../AboutModalBoxHeader'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModalBoxHeader should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxHero.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxHero.test.tsx deleted file mode 100644 index da445ac378e..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalBoxHero.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalBoxHero } from '../../AboutModalBoxHero'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModalBoxHero should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalContainer.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalContainer.test.tsx deleted file mode 100644 index 95cadad61b2..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/AboutModalContainer.test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AboutModalContainer } from '../../AboutModalContainer'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AboutModalContainer should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode
    } - className={"''"} - isOpen={false} - onClose={() => undefined} - productName={"''"} - trademark={'string'} - brandImageSrc={'string'} - brandImageAlt={'string'} - backgroundImageSrc={'string'} - aria-labelledby={'string'} - aria-describedby={'string'} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModal.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModal.test.tsx.snap deleted file mode 100644 index 5b65e14b5b5..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModal.test.tsx.snap +++ /dev/null @@ -1,25 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModal should match snapshot (auto-generated) 1`] = ` -} -> - -
    - ReactNode -
    -
    -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBox.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBox.test.tsx.snap deleted file mode 100644 index 1ba0f3c6d85..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBox.test.tsx.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModalBox should match snapshot (auto-generated) 1`] = ` -
    -
    - ReactNode -
    -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxBrand.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxBrand.test.tsx.snap deleted file mode 100644 index a4d9f884377..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxBrand.test.tsx.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModalBoxBrand should match snapshot (auto-generated) 1`] = ` -
    - string -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxCloseButton.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxCloseButton.test.tsx.snap deleted file mode 100644 index 906c80019b4..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxCloseButton.test.tsx.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModalBoxCloseButton should match snapshot (auto-generated) 1`] = ` -
    - -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxContent.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxContent.test.tsx.snap deleted file mode 100644 index c6c35bb7674..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxContent.test.tsx.snap +++ /dev/null @@ -1,25 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModalBoxContent should match snapshot (auto-generated) 1`] = ` -
    -
    -
    -
    - ReactNode -
    -
    -
    -

    - string -

    -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxHeader.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxHeader.test.tsx.snap deleted file mode 100644 index 28b29e9fa72..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxHeader.test.tsx.snap +++ /dev/null @@ -1,15 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModalBoxHeader should match snapshot (auto-generated) 1`] = ` -
    - - '' - -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxHero.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxHero.test.tsx.snap deleted file mode 100644 index 19f1124ee2d..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalBoxHero.test.tsx.snap +++ /dev/null @@ -1,12 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModalBoxHero should match snapshot (auto-generated) 1`] = ` -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalContainer.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalContainer.test.tsx.snap deleted file mode 100644 index b59bd771782..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/Generated/__snapshots__/AboutModalContainer.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AboutModalContainer should match snapshot (auto-generated) 1`] = `""`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBox.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBox.test.tsx.snap index 2888136341f..a143891d083 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBox.test.tsx.snap +++ b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBox.test.tsx.snap @@ -1,13 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AboutModalBox Test 1`] = ` -
    - This is a AboutModalBox -
    + +
    + This is a AboutModalBox +
    +
    `; diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxBrand.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxBrand.test.tsx.snap index bdae58e086c..3a3c8b7e5bf 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxBrand.test.tsx.snap +++ b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxBrand.test.tsx.snap @@ -1,13 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`test About Modal Brand 1`] = ` -
    - brand -
    + +
    + brand +
    +
    `; diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxCloseButton.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxCloseButton.test.tsx.snap index d9e251eb27d..a49f0976bb0 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxCloseButton.test.tsx.snap +++ b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxCloseButton.test.tsx.snap @@ -1,55 +1,106 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AboutModalBoxCloseButton Test 1`] = ` -
    - -
    + +
    + `; exports[`AboutModalBoxCloseButton Test close button aria label 1`] = ` -
    - -
    + +
    + `; exports[`AboutModalBoxCloseButton Test onclose 1`] = ` -
    - -
    + +
    + `; diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxContent.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxContent.test.tsx.snap index 422175b22e4..444a82eedd1 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxContent.test.tsx.snap +++ b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxContent.test.tsx.snap @@ -1,23 +1,25 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AboutModalBoxContent Test 1`] = ` -
    +
    - This is a AboutModalBoxContent +
    + This is a AboutModalBoxContent +
    +

    + trademark +

    -

    - trademark -

    -
    + `; diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxHeader.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxHeader.test.tsx.snap index e7caeb44e56..aac3b538c69 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxHeader.test.tsx.snap +++ b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxHeader.test.tsx.snap @@ -1,15 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AboutModalBoxHeader Test 1`] = ` -
    - + <div + class="pf-v6-c-about-modal-box__header" > - Product Name - -
    +

    + Product Name +

    +
    + `; diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxHero.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxHero.test.tsx.snap deleted file mode 100644 index 0504632d5e5..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalBoxHero.test.tsx.snap +++ /dev/null @@ -1,12 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`test About Modal Box SHero 1`] = ` -
    -`; diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalContainer.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalContainer.test.tsx.snap deleted file mode 100644 index c1413712bee..00000000000 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalContainer.test.tsx.snap +++ /dev/null @@ -1,48 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`About Modal Container Test isOpen 1`] = ` - - - - - - - - This is ModalBox content - - - - - -`; - -exports[`About Modal Container Test simple 1`] = `""`; - -exports[`About Modal Container Test with onlose 1`] = `""`; diff --git a/packages/react-core/src/components/AboutModal/examples/AboutModal.md b/packages/react-core/src/components/AboutModal/examples/AboutModal.md index 0f7470df817..b6f8635336a 100644 --- a/packages/react-core/src/components/AboutModal/examples/AboutModal.md +++ b/packages/react-core/src/components/AboutModal/examples/AboutModal.md @@ -1,11 +1,13 @@ --- id: About modal section: components -cssPrefix: pf-c-about-modal-box +cssPrefix: pf-v6-c-about-modal-box propComponents: ['AboutModal'] --- -import brandImg from './brandImg.svg'; -import bgImg from './patternfly-orb.svg'; +import { Fragment, useState } from 'react'; +import brandImg from '../../assets/PF-IconLogo.svg'; +import bgImg from '../../assets/pf-background.svg'; +import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing'; ## Examples ### Basic @@ -20,6 +22,3 @@ import bgImg from './patternfly-orb.svg'; ```ts file="./AboutModalComplexUserPositionedContent.tsx" ``` -### Custom background image -```ts file="./AboutModalCustomBackgroundImage.tsx" -``` diff --git a/packages/react-core/src/components/AboutModal/examples/AboutModalBasic.tsx b/packages/react-core/src/components/AboutModal/examples/AboutModalBasic.tsx index 3a20a8743d0..a8b5754f452 100644 --- a/packages/react-core/src/components/AboutModal/examples/AboutModalBasic.tsx +++ b/packages/react-core/src/components/AboutModal/examples/AboutModalBasic.tsx @@ -1,46 +1,47 @@ -import React from 'react'; -import { AboutModal, Button, TextContent, TextList, TextListItem } from '@patternfly/react-core'; -import brandImg from './brandImg.svg'; +import { Fragment, useState } from 'react'; +import { AboutModal, Button, Content } from '@patternfly/react-core'; +import brandImg from '../../assets/PF-IconLogo.svg'; export const AboutModalBasic: React.FunctionComponent = () => { - const [isModalOpen, setIsModalOpen] = React.useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); - const toggleModal = () => { + const toggleModal = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => { setIsModalOpen(!isModalOpen); }; return ( - + | KeyboardEvent | MouseEvent) => toggleModal(e)} trademark="Trademark and copyright information here" brandImageSrc={brandImg} brandImageAlt="Patternfly Logo" - productName="Product Name" + backgroundImageSrc="/assets/images/pf-background.svg" + productName="name" > - - - CFME Version - 5.5.3.4.20102789036450 - Cloudforms Version - 4.1 - Server Name - 40DemoMaster - User Name - Administrator - User Role - EvmRole-super_administrator - Browser Version - 601.2 - Browser OS - Mac - - + +
    +
    CFME version
    +
    5.5.3.4.20102789036450
    +
    Cloudforms Version
    +
    4.1
    +
    Server name
    +
    40DemoMaster
    +
    User name
    +
    Administrator
    +
    User role
    +
    EvmRole-super_administrator
    +
    Browser version
    +
    601.2
    +
    Browser OS
    +
    Mac
    +
    +
    -
    + ); }; diff --git a/packages/react-core/src/components/AboutModal/examples/AboutModalComplexUserPositionedContent.tsx b/packages/react-core/src/components/AboutModal/examples/AboutModalComplexUserPositionedContent.tsx index 916b5ed322f..45e0d9ce159 100644 --- a/packages/react-core/src/components/AboutModal/examples/AboutModalComplexUserPositionedContent.tsx +++ b/packages/react-core/src/components/AboutModal/examples/AboutModalComplexUserPositionedContent.tsx @@ -1,52 +1,54 @@ -import React from 'react'; -import { AboutModal, Alert, Button, TextContent, TextList, TextListItem } from '@patternfly/react-core'; -import brandImg from './brandImg.svg'; +import { Fragment, useState } from 'react'; +import { AboutModal, Alert, Button, Content } from '@patternfly/react-core'; +import brandImg from '../../assets/PF-IconLogo.svg'; +import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing'; export const AboutModalComplexUserPositionedContent: React.FunctionComponent = () => { - const [isModalOpen, setIsModalOpen] = React.useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); - const toggleModal = () => { + const toggleModal = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => { setIsModalOpen(!isModalOpen); }; return ( - + | KeyboardEvent | MouseEvent) => toggleModal(e)} trademark="Trademark and copyright information here" brandImageSrc={brandImg} brandImageAlt="Patternfly Logo" - noAboutModalBoxContentContainer={true} - productName="Product Name" + backgroundImageSrc="/assets/images/pf-background.svg" + hasNoContentContainer={true} + productName="Product name" > - +

    About

    Content here

    -
    + - - - CFME Version - 5.5.3.4.20102789036450 - Cloudforms Version - 4.1 - Server Name - 40DemoMaster - User Name - Administrator - User Role - EvmRole-super_administrator - Browser Version - 601.2 - Browser OS - Mac - - + +
    +
    CFME version
    +
    5.5.3.4.20102789036450
    +
    Cloudforms version
    +
    4.1
    +
    Server name
    +
    40DemoMaster
    +
    User name
    +
    Administrator
    +
    User role
    +
    EvmRole-super_administrator
    +
    Browser version
    +
    601.2
    +
    Browser OS
    +
    Mac
    +
    +
    -
    + ); }; diff --git a/packages/react-core/src/components/AboutModal/examples/AboutModalCustomBackgroundImage.tsx b/packages/react-core/src/components/AboutModal/examples/AboutModalCustomBackgroundImage.tsx deleted file mode 100644 index 3bcc7ed013d..00000000000 --- a/packages/react-core/src/components/AboutModal/examples/AboutModalCustomBackgroundImage.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import { AboutModal, Button, TextContent, TextList, TextListItem } from '@patternfly/react-core'; -import brandImg from './brandImg.svg'; -import bgImg from './patternfly-orb.svg'; - -export const AboutModalCustomBackgroundImage: React.FunctionComponent = () => { - const [isModalOpen, setIsModalOpen] = React.useState(false); - - const toggleModal = () => { - setIsModalOpen(!isModalOpen); - }; - - return ( - - - - - - CFME Version - 5.5.3.4.20102789036450 - - - - - ); -}; diff --git a/packages/react-core/src/components/AboutModal/examples/AboutModalWithoutProductName.tsx b/packages/react-core/src/components/AboutModal/examples/AboutModalWithoutProductName.tsx index 1870c112617..c9073da724c 100644 --- a/packages/react-core/src/components/AboutModal/examples/AboutModalWithoutProductName.tsx +++ b/packages/react-core/src/components/AboutModal/examples/AboutModalWithoutProductName.tsx @@ -1,45 +1,47 @@ -import React from 'react'; -import { AboutModal, Button, TextContent, TextList, TextListItem } from '@patternfly/react-core'; -import brandImg from './brandImg.svg'; +import { Fragment, useState } from 'react'; +import { AboutModal, Button, Content } from '@patternfly/react-core'; +import brandImg from '../../assets/PF-IconLogo.svg'; export const AboutModalWithoutProductName: React.FunctionComponent = () => { - const [isModalOpen, setIsModalOpen] = React.useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); - const toggleModal = () => { + const toggleModal = (_event: React.MouseEvent | KeyboardEvent | MouseEvent) => { setIsModalOpen(!isModalOpen); }; return ( - + | KeyboardEvent | MouseEvent) => toggleModal(e)} trademark="Trademark and copyright information here" brandImageSrc={brandImg} brandImageAlt="Patternfly Logo" + backgroundImageSrc="/assets/images/pf-background.svg" + aria-label="No product name about modal" > - - - CFME Version - 5.5.3.4.20102789036450 - Cloudforms Version - 4.1 - Server Name - 40DemoMaster - User Name - Administrator - User Role - EvmRole-super_administrator - Browser Version - 601.2 - Browser OS - Mac - - + +
    +
    CFME version
    +
    5.5.3.4.20102789036450
    +
    Cloudforms version
    +
    4.1
    +
    Server name
    +
    40DemoMaster
    +
    User name
    +
    Administrator
    +
    User role
    +
    EvmRole-super_administrator
    +
    Browser version
    +
    601.2
    +
    Browser OS
    +
    Mac
    +
    +
    -
    + ); }; diff --git a/packages/react-core/src/components/AboutModal/examples/logoImg.svg b/packages/react-core/src/components/AboutModal/examples/logoImg.svg deleted file mode 100644 index efca381b551..00000000000 --- a/packages/react-core/src/components/AboutModal/examples/logoImg.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/packages/react-core/src/components/Accordion/Accordion.tsx b/packages/react-core/src/components/Accordion/Accordion.tsx index a0d69fd3cae..64b9c16898c 100644 --- a/packages/react-core/src/components/Accordion/Accordion.tsx +++ b/packages/react-core/src/components/Accordion/Accordion.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; import { AccordionContext } from './AccordionContext'; @@ -16,18 +15,27 @@ export interface AccordionProps extends React.HTMLProps { asDefinitionList?: boolean; /** Flag to indicate the accordion had a border */ isBordered?: boolean; + /** @beta Flag to prevent the accordion from automatically applying plain styling when glass theme is enabled. */ + isNoPlainOnGlass?: boolean; + /** @beta Flag to add plain styling to the accordion. */ + isPlain?: boolean; /** Display size variant. */ - displaySize?: 'default' | 'large'; + displaySize?: 'default' | 'lg'; + /** Sets the toggle icon position for all accordion toggles. */ + togglePosition?: 'start' | 'end'; } export const Accordion: React.FunctionComponent = ({ children = null, className = '', - 'aria-label': ariaLabel = '', + 'aria-label': ariaLabel, headingLevel = 'h3', asDefinitionList = true, isBordered = false, + isNoPlainOnGlass = false, + isPlain = false, displaySize = 'default', + togglePosition = 'end', ...props }: AccordionProps) => { const AccordionList: any = asDefinitionList ? 'dl' : 'div'; @@ -36,16 +44,21 @@ export const Accordion: React.FunctionComponent = ({ className={css( styles.accordion, isBordered && styles.modifiers.bordered, - displaySize === 'large' && styles.modifiers.displayLg, + isNoPlainOnGlass && styles.modifiers.noPlainOnGlass, + isPlain && styles.modifiers.plain, + togglePosition === 'start' && styles.modifiers.toggleStart, + displaySize === 'lg' && styles.modifiers.displayLg, className )} aria-label={ariaLabel} + {...(!asDefinitionList && ariaLabel && { role: 'region' })} {...props} > {children} diff --git a/packages/react-core/src/components/Accordion/AccordionContent.tsx b/packages/react-core/src/components/Accordion/AccordionContent.tsx index 195d2030409..afb495f5988 100644 --- a/packages/react-core/src/components/Accordion/AccordionContent.tsx +++ b/packages/react-core/src/components/Accordion/AccordionContent.tsx @@ -1,8 +1,9 @@ -import * as React from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; + import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; -import { AccordionContext } from './AccordionContext'; -import { AccordionExpandedContentBody } from './AccordionExpandedContentBody'; +import { AccordionContext, AccordionItemContext } from './AccordionContext'; +import { AccordionExpandableContentBody, AccordionExpandableContentBodyProps } from './AccordionExpandableContentBody'; export interface AccordionContentProps extends React.HTMLProps { /** Content rendered inside the Accordion */ @@ -11,49 +12,71 @@ export interface AccordionContentProps extends React.HTMLProps { className?: string; /** Identify the AccordionContent item */ id?: string; - /** Flag to show if the expanded content of the Accordion item is visible */ - isHidden?: boolean; /** Flag to indicate Accordion content is fixed */ isFixed?: boolean; /** Adds accessible text to the Accordion content */ 'aria-label'?: string; + /** Id of the controlling accordion toggle to label the content. */ + 'aria-labelledby'?: string; /** Component to use as content container */ component?: React.ElementType; /** Flag indicating content is custom. Expanded content Body wrapper will be removed from children. This allows multiple bodies to be rendered as content. */ isCustomContent?: React.ReactNode; + /** Props passed to the AccordionExpandableContentBody **/ + contentBodyProps?: AccordionExpandableContentBodyProps; } export const AccordionContent: React.FunctionComponent = ({ className = '', children = null, id = '', - isHidden = false, isFixed = false, isCustomContent = false, 'aria-label': ariaLabel = '', + 'aria-labelledby': ariaLabelledby, component, + contentBodyProps, ...props -}: AccordionContentProps) => ( - - {({ ContentContainer }) => { - const Container = component || ContentContainer; - return ( - - ); - }} - -); +}: AccordionContentProps) => { + const [hasScrollbar, setHasScrollbar] = useState(false); + const containerRef = useRef(null); + const { isExpanded } = useContext(AccordionItemContext); + + useEffect(() => { + if (containerRef?.current && isFixed && isExpanded) { + const { offsetHeight, scrollHeight } = containerRef.current; + + setHasScrollbar(offsetHeight < scrollHeight); + } else if (!isFixed) { + setHasScrollbar(false); + } + }, [containerRef, isFixed, isExpanded]); + + return ( + + {({ ContentContainer }) => { + const Container = component || ContentContainer; + return ( + + ); + }} + + ); +}; AccordionContent.displayName = 'AccordionContent'; diff --git a/packages/react-core/src/components/Accordion/AccordionContext.ts b/packages/react-core/src/components/Accordion/AccordionContext.ts index 8df38f401fa..c476f15898e 100644 --- a/packages/react-core/src/components/Accordion/AccordionContext.ts +++ b/packages/react-core/src/components/Accordion/AccordionContext.ts @@ -1,8 +1,13 @@ -import * as React from 'react'; - +import { createContext } from 'react'; interface AccordionContextProps { ContentContainer: React.ElementType; ToggleContainer: React.ElementType; + togglePosition: 'start' | 'end'; +} + +interface AccordionItemContextProps { + isExpanded?: boolean; } -export const AccordionContext = React.createContext>({}); +export const AccordionContext = createContext>({}); +export const AccordionItemContext = createContext({} as AccordionItemContextProps); diff --git a/packages/react-core/src/components/Accordion/AccordionExpandableContentBody.tsx b/packages/react-core/src/components/Accordion/AccordionExpandableContentBody.tsx new file mode 100644 index 00000000000..ad04610d16a --- /dev/null +++ b/packages/react-core/src/components/Accordion/AccordionExpandableContentBody.tsx @@ -0,0 +1,17 @@ +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; + +export interface AccordionExpandableContentBodyProps extends React.HTMLProps { + /** Content rendered inside the accordion content body */ + children?: React.ReactNode; +} + +export const AccordionExpandableContentBody: React.FunctionComponent = ({ + children = null, + ...props +}: AccordionExpandableContentBodyProps) => ( +
    + {children} +
    +); +AccordionExpandableContentBody.displayName = 'AccordionExpandableContentBody'; diff --git a/packages/react-core/src/components/Accordion/AccordionExpandedContentBody.tsx b/packages/react-core/src/components/Accordion/AccordionExpandedContentBody.tsx deleted file mode 100644 index bb71be7d721..00000000000 --- a/packages/react-core/src/components/Accordion/AccordionExpandedContentBody.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; - -export interface AccordionExpandedContentBodyProps { - /** Content rendered inside the accordion content body */ - children?: React.ReactNode; -} - -export const AccordionExpandedContentBody: React.FunctionComponent = ({ - children = null -}: AccordionExpandedContentBodyProps) =>
    {children}
    ; -AccordionExpandedContentBody.displayName = 'AccordionExpandedContentBody'; diff --git a/packages/react-core/src/components/Accordion/AccordionItem.tsx b/packages/react-core/src/components/Accordion/AccordionItem.tsx index f4c413d479a..07c1d7ab16e 100644 --- a/packages/react-core/src/components/Accordion/AccordionItem.tsx +++ b/packages/react-core/src/components/Accordion/AccordionItem.tsx @@ -1,11 +1,30 @@ -import * as React from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; +import { AccordionItemContext } from './AccordionContext'; -export interface AccordionItemProps { - /** Content rendered inside the Accordion item */ +export interface AccordionItemProps extends React.HTMLProps { + /** Content rendered inside the accordion item. */ children?: React.ReactNode; + /** Additional classes added to the accordion item. */ + className?: string; + /** Flag to indicate whether the accordion item is expanded. */ + isExpanded?: boolean; } -export const AccordionItem: React.FunctionComponent = ({ children = null }: AccordionItemProps) => ( - {children} +export const AccordionItem: React.FunctionComponent = ({ + children = null, + className, + isExpanded: isExpandedProp = false, + ...props +}: AccordionItemProps) => ( + +
    + {children} +
    +
    ); AccordionItem.displayName = 'AccordionItem'; diff --git a/packages/react-core/src/components/Accordion/AccordionToggle.tsx b/packages/react-core/src/components/Accordion/AccordionToggle.tsx index a2ec5b28124..04d3467a57c 100644 --- a/packages/react-core/src/components/Accordion/AccordionToggle.tsx +++ b/packages/react-core/src/components/Accordion/AccordionToggle.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; +import { useContext } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; -import { AccordionContext } from './AccordionContext'; +import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon'; +import { AccordionContext, AccordionItemContext } from './AccordionContext'; -export interface AccordionToggleProps - extends React.DetailedHTMLProps, HTMLButtonElement> { +export interface AccordionToggleProps extends React.DetailedHTMLProps< + React.ButtonHTMLAttributes, + HTMLButtonElement +> { /** Content rendered inside the Accordion toggle */ children?: React.ReactNode; /** Additional classes added to the Accordion Toggle */ className?: string; - /** Flag to show if the expanded content of the Accordion item is visible */ - isExpanded?: boolean; /** Identify the Accordion toggle number */ id: string; /** Container to override the default for toggle */ @@ -21,31 +21,41 @@ export interface AccordionToggleProps export const AccordionToggle: React.FunctionComponent = ({ className = '', id, - isExpanded = false, children = null, component, ...props -}: AccordionToggleProps) => ( - - {({ ToggleContainer }) => { - const Container = component || ToggleContainer; - return ( - - - - ); - }} - -); +}: AccordionToggleProps) => { + const renderToggleIcon = () => ( + + + + ); + + const { isExpanded } = useContext(AccordionItemContext); + + return ( + + {({ ToggleContainer, togglePosition }) => { + const Container = component || ToggleContainer; + const isToggleStartPositioned = togglePosition === 'start'; + + return ( + + + + ); + }} + + ); +}; AccordionToggle.displayName = 'AccordionToggle'; diff --git a/packages/react-core/src/components/Accordion/__tests__/Accordion.test.tsx b/packages/react-core/src/components/Accordion/__tests__/Accordion.test.tsx index 843097ccfcd..7cfe2a82ba7 100644 --- a/packages/react-core/src/components/Accordion/__tests__/Accordion.test.tsx +++ b/packages/react-core/src/components/Accordion/__tests__/Accordion.test.tsx @@ -1,104 +1,187 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; + import { Accordion } from '../Accordion'; -import { AccordionToggle } from '../AccordionToggle'; -import { AccordionContent } from '../AccordionContent'; -import { AccordionItem } from '../AccordionItem'; -import { AccordionExpandedContentBody } from '../AccordionExpandedContentBody'; - -describe('Accordion', () => { - test('Accordion default', () => { - const view = shallow(); - expect(view.render()).toMatchSnapshot(); - }); - - test('Accordion with non-default headingLevel', () => { - const view = shallow( - - - Item One - Item One Content - - - ); - expect(view.render()).toMatchSnapshot(); - }); - - test('It should pass optional aria props', () => { - const view = mount( - - - - ); - const button = view.find('button[id="ex-toggle2"]').getElement(); - expect(button.props['aria-label']).toBe('Toggle details for'); - expect(button.props['aria-labelledby']).toBe('ex-toggle2 ex-item2'); - expect(button.props['aria-expanded']).toBe(false); - }); - - test('Toggle expanded', () => { - const view = mount( - - - - ); - const button = view.find('button[id="ex-toggle2"]').getElement(); - expect(button.props['aria-expanded']).toBe(true); - expect(button.props.className).toContain('pf-m-expanded'); - }); - - test('Custom containers', () => { - const container = 'a'; - const view = mount( - - - - Item One - - Item One Content - - - ); - expect(view.find(AccordionToggle).getDOMNode().tagName).toBe(container.toLocaleUpperCase()); - expect(view.find(AccordionContent).getDOMNode().tagName).toBe(container.toLocaleUpperCase()); - }); - - test('Accordion bordered', () => { - const view = shallow( - - - Item One - Item One Content - - - ); - expect(view.render()).toMatchSnapshot(); - }); - - test('Accordion display large', () => { - const view = shallow( - - - Item One - Item One Content - - - ); - expect(view.render()).toMatchSnapshot(); - }); - - test('Accordion custom content', () => { - const view = shallow( - - - Item One - - Item one content body 1 - Item one Content body 2 - - - - ); - expect(view.render()).toMatchSnapshot(); - }); +import { AccordionContext } from '../AccordionContext'; +import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; + +test('Renders without children', () => { + render(); + + expect(screen.getByTestId('accordion')).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test('Renders with the passed aria label', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveAccessibleName('Accordion test'); +}); + +test('Renders with inherited element props spread to the component', () => { + render( + <> + Test +

    Label

    + + ); + + expect(screen.getByText('Test')).toHaveAccessibleName('Label'); +}); + +test(`Renders with class name ${styles.accordion}`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.accordion); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('test-class'); +}); + +test('Renders Accordion as a "dl" by default', () => { + render(Test); + + /* these tests asserting a nodeName property aren't my favorite, but dl and div elements don't have implicit aria + roles for us to select/assert against with something more directly meaningful to user experience */ + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'DL'); +}); + +test('Renders Accordion as a "div" when asDefinitionList is false', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'DIV'); +}); + +test('Provides a ContentContainer of "dd" in a context by default', () => { + render( + + {({ ContentContainer }) => ContentContainer} + + ); + + expect(screen.getByText('dd')).toBeVisible(); +}); + +test('Provides a ContentContainer of "div" in a context when asDefinitionList is false', () => { + render( + + {({ ContentContainer }) => ContentContainer} + + ); + + expect(screen.getByText('div')).toBeVisible(); +}); + +test('Provides a ToggleContainer of "dt" in a context by default', () => { + render( + + {({ ToggleContainer }) => ToggleContainer} + + ); + + expect(screen.getByText('dt')).toBeVisible(); +}); + +test('Provides a ToggleContainer of "h3" in a context when asDefinitionList is false', () => { + render( + + {({ ToggleContainer }) => ToggleContainer} + + ); + + expect(screen.getByText('h3')).toBeVisible(); +}); + +test('Provides a ToggleContainer of "h2" in a context when asDefinitionList is false and headingLevel is "h2"', () => { + render( + + {({ ToggleContainer }) => ToggleContainer} + + ); + + expect(screen.getByText('h2')).toBeVisible(); +}); + +test('Renders without pf-m-bordered by default', () => { + render(Test); + + expect(screen.getByText('Test')).not.toHaveClass('pf-m-bordered'); +}); + +test('Renders with pf-m-bordered when isBordered=true', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('pf-m-bordered'); +}); + +test(`Renders without class ${styles.modifiers.noPlainOnGlass} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).not.toHaveClass(styles.modifiers.noPlainOnGlass); +}); + +test(`Renders with class ${styles.modifiers.noPlainOnGlass} when isNoPlainOnGlass`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.noPlainOnGlass); +}); + +test(`Renders without class ${styles.modifiers.plain} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).not.toHaveClass(styles.modifiers.plain); +}); + +test(`Renders with class ${styles.modifiers.plain} when isPlain`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.plain); +}); + +test(`applies both ${styles.modifiers.plain} and ${styles.modifiers.noPlainOnGlass} when both isPlain and isNoPlainOnGlass are true`, () => { + render( + + Test + + ); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.plain); + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.noPlainOnGlass); +}); + +test('Renders without pf-m-display-lg by default', () => { + render(Test); + + expect(screen.getByText('Test')).not.toHaveClass('pf-m-display-lg'); +}); + +test('Renders with pf-m-display-lg when displaySize="lg"', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('pf-m-display-lg'); +}); + +test(`Renders without class ${styles.modifiers.toggleStart} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).not.toHaveClass(styles.modifiers.toggleStart); +}); + +test(`Renders with class ${styles.modifiers.toggleStart} when togglePosition='start'`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.toggleStart); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Accordion/__tests__/AccordionContent.test.tsx b/packages/react-core/src/components/Accordion/__tests__/AccordionContent.test.tsx new file mode 100644 index 00000000000..84f5ef02d43 --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/AccordionContent.test.tsx @@ -0,0 +1,220 @@ +import { render, screen } from '@testing-library/react'; + +import { AccordionContent } from '../AccordionContent'; +import { AccordionContext, AccordionItemContext } from '../AccordionContext'; +import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; + +jest.mock('../AccordionExpandableContentBody', () => ({ + AccordionExpandableContentBody: ({ children }) =>
    {children}
    +})); + +test('Renders without children', () => { + render( + + + + + + ); + + expect(screen.getByTestId('accordion-content')).toBeVisible(); +}); + +test('Renders children', () => { + render( + + + Test + + + ); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test('Renders with children wrapped in AccordionExpandableContentBody by default', () => { + render( + + + Test + + + ); + + expect(screen.getByText('Test')).toHaveAccessibleName('Expanded content body mock'); +}); + +test('Does not render children wrapped in AccordionExpandableContentBody when isCustomContent=true', () => { + render( + + + Test + + + ); + + expect(screen.getByText('Test')).not.toHaveAccessibleName('Expanded content body mock'); +}); + +test('Renders with the passed aria label', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading')).toHaveAccessibleName('Accordion content'); +}); + +test('Renders with the passed aria-labelledby', () => { + render( + <> +
    Accordion content
    + + + Test + + + + ); + + expect(screen.getByRole('heading')).toHaveAccessibleName('Accordion content'); +}); + +test('Renders with inherited element props spread to the component', () => { + render( + <> + + + Test + +

    Label

    +
    + + ); + + expect(screen.getByRole('heading')).toHaveAccessibleName('Label'); +}); + +test(`Renders with class name ${styles.accordionExpandableContent}`, () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading')).toHaveClass(styles.accordionExpandableContent); +}); + +test('Renders with custom class names provided via prop', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading')).toHaveClass('test-class'); +}); + +test('Renders with the id prop passed to the container', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading')).toHaveProperty('id', 'test-id'); +}); + +test('Renders the container as the element provided in ContentContainer from a context by default', () => { + render( + + + Test + + + ); + + expect(screen.queryByRole('heading', { level: 1 })).not.toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 3 })).toBeVisible(); +}); + +test('Renders as the element provided via the component prop when one is provided', () => { + render( + + + Test + + + ); + + expect(screen.queryByRole('heading', { level: 3 })).not.toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 1 })).toBeVisible(); +}); + +test('Renders the container as hidden when isExpanded from context is false', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading', { hidden: true })).toHaveAttribute('hidden'); +}); + +test('Renders the container as not hidden when isExpanded from context is true', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading', { level: 3 })).not.toHaveAttribute('hidden'); +}); + +test('Renders without pf-m-fixed by default', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading')).not.toHaveClass('pf-m-fixed'); +}); + +test('Renders with pf-m-fixed when isFixed is true', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('heading')).toHaveClass('pf-m-fixed'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + + + Test + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Accordion/__tests__/AccordionExpandedContentBody.test.tsx b/packages/react-core/src/components/Accordion/__tests__/AccordionExpandedContentBody.test.tsx new file mode 100644 index 00000000000..3070148b556 --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/AccordionExpandedContentBody.test.tsx @@ -0,0 +1,30 @@ +import { render, screen } from '@testing-library/react'; + +import { AccordionExpandableContentBody } from '../AccordionExpandableContentBody'; +import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; + +test('Renders without children', () => { + const { asFragment } = render(); + + /* a snapshot test is used here because this component isn't selectable via better screen queries without children + as it doesn't spread other props to its container + */ + expect(asFragment()).toMatchSnapshot(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with class name ${styles.accordionExpandableContentBody}`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.accordionExpandableContentBody); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Accordion/__tests__/AccordionItem.test.tsx b/packages/react-core/src/components/Accordion/__tests__/AccordionItem.test.tsx new file mode 100644 index 00000000000..f48a5cfedbe --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/AccordionItem.test.tsx @@ -0,0 +1,38 @@ +import { render, screen } from '@testing-library/react'; +import { AccordionItem } from '../AccordionItem'; +import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with class ${styles.accordionItem} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.accordionItem, { exact: true }); +}); + +test(`Renders with class ${styles.modifiers.expanded} when isExpanded is true`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.expanded); +}); + +test(`Renders with additional classes when className is passed`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Spreads props if others are passed`, () => { + render(Test); + + expect(screen.getByTestId('testId')).toBeInTheDocument(); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Accordion/__tests__/AccordionToggle.test.tsx b/packages/react-core/src/components/Accordion/__tests__/AccordionToggle.test.tsx new file mode 100644 index 00000000000..1a67f3deee2 --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/AccordionToggle.test.tsx @@ -0,0 +1,277 @@ +import { render, screen } from '@testing-library/react'; + +import { AccordionToggle } from '../AccordionToggle'; +import { AccordionContext, AccordionItemContext } from '../AccordionContext'; +import styles from '@patternfly/react-styles/css/components/Accordion/accordion'; + +jest.mock('@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon', () => () => 'Icon mock'); + +test('Renders without children', () => { + render( + + + + ); + + expect(screen.getByTestId('accordion-toggle-test-id')).toBeVisible(); +}); + +test('Renders children', () => { + render( + + Test + + ); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test('Renders with inherited element props spread to the component', () => { + render( + <> + + + Test + +

    Label

    +
    + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Label'); +}); + +test(`Renders the accordion toggle with class ${styles.accordionToggle}`, () => { + render( + + + Test + + + ); + + expect(screen.getByRole('button')).toHaveClass(styles.accordionToggle); +}); + +test('Renders the accordion toggle with custom class names provided via prop', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('button')).toHaveClass('test-class'); +}); + +test(`Renders with children inside class ${styles.accordionToggleText}`, () => { + render( + + + Test + + + ); + + expect(screen.getByText('Test')).toHaveClass(styles.accordionToggleText); +}); + +test(`Renders with the toggle icon inside class ${styles.accordionToggleIcon}`, () => { + render( + + + Test + + + ); + + expect(screen.getByText('Icon mock')).toHaveClass(styles.accordionToggleIcon); +}); + +test('Renders with the id prop passed to the toggle', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('button')).toHaveProperty('id', 'accordion-toggle'); +}); + +test('Renders the container as the element provided in ToggleContainer from a context by default', () => { + render( + + Test + + ); + + expect(screen.queryByRole('heading', { level: 1 })).not.toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 3 })).toBeVisible(); +}); + +test('Renders the container as the element provided via the component prop when one is provided', () => { + render( + + + Test + + + ); + + expect(screen.queryByRole('heading', { level: 3 })).not.toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 1 })).toBeVisible(); +}); + +test('Renders the toggle with aria-expanded=false when isExpanded from context is false', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle).toHaveAttribute('aria-expanded', 'false'); +}); + +test('Renders the toggle with aria-expanded=true when isExpanded from context is true', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle).toHaveAttribute('aria-expanded', 'true'); +}); + +test('Renders toggle text before toggle icon by default', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleText); +}); + +test('Renders toggle icon before toggle text when togglePosition from context = "start"', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleIcon); +}); + +test('Renders toggle text before toggle icon by default', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleText); +}); + +test('Renders toggle icon before toggle text when togglePosition from context = "start"', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleIcon); +}); + +test('Renders toggle text before toggle icon by default', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleText); +}); + +test('Renders toggle icon before toggle text when togglePosition from context = "start"', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleIcon); +}); + +test('Renders toggle text before toggle icon by default', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleText); +}); + +test('Renders toggle icon before toggle text when togglePosition from context = "start"', () => { + render( + + + Test + + + ); + + const toggle = screen.getByRole('button'); + + expect(toggle.firstChild).toHaveClass(styles.accordionToggleIcon); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + + + Test + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/Accordion.test.tsx b/packages/react-core/src/components/Accordion/__tests__/Generated/Accordion.test.tsx deleted file mode 100644 index 4fb0618b238..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/Accordion.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Accordion } from '../../Accordion'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Accordion should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - aria-label={"''"} - headingLevel={'h3'} - asDefinitionList={true} - noBoxShadow={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionContent.test.tsx b/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionContent.test.tsx deleted file mode 100644 index 2fefd7bbe63..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionContent.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AccordionContent } from '../../AccordionContent'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AccordionContent should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - id={"''"} - isHidden={false} - isFixed={false} - aria-label={"''"} - component={() =>
    } - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionItem.test.tsx b/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionItem.test.tsx deleted file mode 100644 index d69ad0a91a6..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionItem.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AccordionItem } from '../../AccordionItem'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AccordionItem should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionToggle.test.tsx b/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionToggle.test.tsx deleted file mode 100644 index 2f9f0a8bc7a..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/AccordionToggle.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AccordionToggle } from '../../AccordionToggle'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AccordionToggle should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - isExpanded={false} - id={'string'} - component={() =>
    } - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/Accordion.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/Accordion.test.tsx.snap deleted file mode 100644 index 4fe6268ceea..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/Accordion.test.tsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Accordion should match snapshot (auto-generated) 1`] = ` -
    - - ReactNode - -
    -`; diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionContent.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionContent.test.tsx.snap deleted file mode 100644 index 5d975bc1ee9..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionContent.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AccordionContent should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionItem.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionItem.test.tsx.snap deleted file mode 100644 index 0c837ab952a..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionItem.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AccordionItem should match snapshot (auto-generated) 1`] = ` - - ReactNode - -`; diff --git a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionToggle.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionToggle.test.tsx.snap deleted file mode 100644 index e67fee810f2..00000000000 --- a/packages/react-core/src/components/Accordion/__tests__/Generated/__snapshots__/AccordionToggle.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AccordionToggle should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap index fe2f163de89..817684b07f3 100644 --- a/packages/react-core/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap +++ b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap @@ -1,213 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Accordion Accordion bordered 1`] = ` -
    -
    - -
    -
    -
    - Item One Content -
    -
    -
    -`; - -exports[`Accordion Accordion custom content 1`] = ` -
    -
    - -
    -
    -
    - Item one content body 1 -
    -
    - Item one Content body 2 -
    -
    -
    -`; - -exports[`Accordion Accordion default 1`] = ` -
    -`; - -exports[`Accordion Accordion display large 1`] = ` -
    -
    - -
    -
    -
    - Item One Content -
    -
    -
    -`; - -exports[`Accordion Accordion with non-default headingLevel 1`] = ` -
    -

    - -

    -
    -
    - Item One Content -
    -
    -
    +exports[`Matches the snapshot 1`] = ` + +
    + `; diff --git a/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionContent.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionContent.test.tsx.snap new file mode 100644 index 00000000000..0ddfb161601 --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionContent.test.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +

    +
    + Test +
    +

    +
    +`; diff --git a/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionExpandedContentBody.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionExpandedContentBody.test.tsx.snap new file mode 100644 index 00000000000..8d125f423a2 --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionExpandedContentBody.test.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + Test +
    +
    +`; + +exports[`Renders without children 1`] = ` + +
    + +`; diff --git a/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionItem.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionItem.test.tsx.snap new file mode 100644 index 00000000000..8b08bc92204 --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionItem.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + Test +
    +
    +`; diff --git a/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionToggle.test.tsx.snap b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionToggle.test.tsx.snap new file mode 100644 index 00000000000..1e880aa22ee --- /dev/null +++ b/packages/react-core/src/components/Accordion/__tests__/__snapshots__/AccordionToggle.test.tsx.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +

    + +

    +
    +`; diff --git a/packages/react-core/src/components/Accordion/examples/Accordion.md b/packages/react-core/src/components/Accordion/examples/Accordion.md index e1c4fcf5af0..56fe2e7231d 100644 --- a/packages/react-core/src/components/Accordion/examples/Accordion.md +++ b/packages/react-core/src/components/Accordion/examples/Accordion.md @@ -1,10 +1,11 @@ --- id: Accordion section: components -cssPrefix: pf-c-accordion -propComponents: ['Accordion', 'AccordionItem', 'AccordionContent', 'AccordionToggle', AccordionExpandedContentBody] +cssPrefix: pf-v6-c-accordion +propComponents: ['Accordion', 'AccordionItem', 'AccordionContent', 'AccordionToggle', AccordionExpandableContentBody] --- +import { useState } from 'react'; import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; ## Examples @@ -28,3 +29,8 @@ import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-i ```ts file="./AccordionBordered.tsx" ``` + +### Toggle icon at start + +```ts file="./AccordionToggleIconAtStart.tsx" +``` diff --git a/packages/react-core/src/components/Accordion/examples/AccordionBordered.tsx b/packages/react-core/src/components/Accordion/examples/AccordionBordered.tsx index 08db9f50487..45b4c6a4272 100644 --- a/packages/react-core/src/components/Accordion/examples/AccordionBordered.tsx +++ b/packages/react-core/src/components/Accordion/examples/AccordionBordered.tsx @@ -1,20 +1,20 @@ -import React from 'react'; +import { useState } from 'react'; import { Accordion, AccordionItem, AccordionContent, AccordionToggle, - AccordionExpandedContentBody, + AccordionExpandableContentBody, Button, Checkbox } from '@patternfly/react-core'; import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; export const AccordionBordered: React.FunctionComponent = () => { - const [expanded, setExpanded] = React.useState('ex-toggle4'); - const [isDisplayLarge, setIsDisplayLarge] = React.useState(false); + const [expanded, setExpanded] = useState('bordered-toggle4'); + const [isDisplayLarge, setIsDisplayLarge] = useState(false); - const displaySize = isDisplayLarge ? 'large' : 'default'; + const displaySize = isDisplayLarge ? 'lg' : 'default'; const onToggle = (id: string) => { if (id === expanded) { setExpanded(''); @@ -26,17 +26,16 @@ export const AccordionBordered: React.FunctionComponent = () => { return ( <> - + { - onToggle('ex-toggle1'); + onToggle('bordered-toggle1'); }} - isExpanded={expanded === 'ex-toggle1'} - id="ex-toggle1" + id="bordered-toggle1" > Item one - +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. @@ -44,17 +43,16 @@ export const AccordionBordered: React.FunctionComponent = () => { - + { - onToggle('ex-toggle2'); + onToggle('bordered-toggle2'); }} - isExpanded={expanded === 'ex-toggle2'} - id="ex-toggle2" + id="bordered-toggle2" > Item two - +

    Vivamus et tortor sed arcu congue vehicula eget et diam. Praesent nec dictum lorem. Aliquam id diam ultrices, faucibus erat id, maximus nunc. @@ -62,33 +60,31 @@ export const AccordionBordered: React.FunctionComponent = () => { - + { - onToggle('ex-toggle3'); + onToggle('bordered-toggle3'); }} - isExpanded={expanded === 'ex-toggle3'} - id="ex-toggle3" + id="bordered-toggle3" > Item three - +

    Morbi vitae urna quis nunc convallis hendrerit. Aliquam congue orci quis ultricies tempus.

    - + { - onToggle('ex-toggle4'); + onToggle('bordered-toggle4'); }} - isExpanded={expanded === 'ex-toggle4'} - id="ex-toggle4" + id="bordered-toggle4" > Item four - - + + Donec vel posuere orci. Phasellus quis tortor a ex hendrerit efficitur. Aliquam lacinia ligula pharetra, sagittis ex ut, pellentesque diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum ultricies nulla nibh. Etiam vel dui fermentum ligula ullamcorper @@ -96,25 +92,24 @@ export const AccordionBordered: React.FunctionComponent = () => { parturient montes, nascetur ridiculus mus. Mauris et velit neque. Donec ultricies condimentum mauris, pellentesque imperdiet libero convallis convallis. Aliquam erat volutpat. Donec rutrum semper tempus. Proin dictum imperdiet nibh, quis dapibus nulla. Integer sed tincidunt lectus, sit amet auctor eros. - - - - + - + { - onToggle('ex-toggle5'); + onToggle('bordered-toggle5'); }} - isExpanded={expanded === 'ex-toggle5'} - id="ex-toggle5" + id="bordered-toggle5" > Item five - +

    Vivamus finibus dictum ex id ultrices. Mauris dictum neque a iaculis blandit.

    @@ -123,8 +118,8 @@ export const AccordionBordered: React.FunctionComponent = () => { setIsDisplayLarge(checked)} + aria-label="show display large variation checkbox" id="toggle-display-lg" name="toggle-display-lg" /> diff --git a/packages/react-core/src/components/Accordion/examples/AccordionDefinitionList.tsx b/packages/react-core/src/components/Accordion/examples/AccordionDefinitionList.tsx index 3e011986b79..c0cf781da5d 100644 --- a/packages/react-core/src/components/Accordion/examples/AccordionDefinitionList.tsx +++ b/packages/react-core/src/components/Accordion/examples/AccordionDefinitionList.tsx @@ -1,8 +1,8 @@ -import React from 'react'; +import { useState } from 'react'; import { Accordion, AccordionItem, AccordionContent, AccordionToggle } from '@patternfly/react-core'; export const AccordionDefinitionList: React.FunctionComponent = () => { - const [expanded, setExpanded] = React.useState('ex-toggle2'); + const [expanded, setExpanded] = useState('def-list-toggle2'); const onToggle = (id: string) => { if (id === expanded) { @@ -14,17 +14,16 @@ export const AccordionDefinitionList: React.FunctionComponent = () => { return ( - + { - onToggle('ex-toggle1'); + onToggle('def-list-toggle1'); }} - isExpanded={expanded === 'ex-toggle1'} - id="ex-toggle1" + id="def-list-toggle1" > Item one - +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. @@ -32,17 +31,16 @@ export const AccordionDefinitionList: React.FunctionComponent = () => { - + { - onToggle('ex-toggle2'); + onToggle('def-list-toggle2'); }} - isExpanded={expanded === 'ex-toggle2'} - id="ex-toggle2" + id="def-list-toggle2" > Item two - +

    Vivamus et tortor sed arcu congue vehicula eget et diam. Praesent nec dictum lorem. Aliquam id diam ultrices, faucibus erat id, maximus nunc. @@ -50,32 +48,30 @@ export const AccordionDefinitionList: React.FunctionComponent = () => { - + { - onToggle('ex-toggle3'); + onToggle('def-list-toggle3'); }} - isExpanded={expanded === 'ex-toggle3'} - id="ex-toggle3" + id="def-list-toggle3" > Item three - +

    Morbi vitae urna quis nunc convallis hendrerit. Aliquam congue orci quis ultricies tempus.

    - + { - onToggle('ex-toggle4'); + onToggle('def-list-toggle4'); }} - isExpanded={expanded === 'ex-toggle4'} - id="ex-toggle4" + id="def-list-toggle4" > Item four - +

    Donec vel posuere orci. Phasellus quis tortor a ex hendrerit efficitur. Aliquam lacinia ligula pharetra, sagittis ex ut, pellentesque diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere @@ -88,17 +84,16 @@ export const AccordionDefinitionList: React.FunctionComponent = () => { - + { - onToggle('ex-toggle5'); + onToggle('def-list-toggle5'); }} - isExpanded={expanded === 'ex-toggle5'} - id="ex-toggle5" + id="def-list-toggle5" > Item five - +

    Vivamus finibus dictum ex id ultrices. Mauris dictum neque a iaculis blandit.

    diff --git a/packages/react-core/src/components/Accordion/examples/AccordionFixedWithMultipleExpandBehavior.tsx b/packages/react-core/src/components/Accordion/examples/AccordionFixedWithMultipleExpandBehavior.tsx index bf03fae38e7..2ae7cdd7605 100644 --- a/packages/react-core/src/components/Accordion/examples/AccordionFixedWithMultipleExpandBehavior.tsx +++ b/packages/react-core/src/components/Accordion/examples/AccordionFixedWithMultipleExpandBehavior.tsx @@ -1,10 +1,10 @@ -import React from 'react'; +import { useState } from 'react'; import { Accordion, AccordionItem, AccordionContent, AccordionToggle } from '@patternfly/react-core'; export const AccordionFixedWithMultipleExpandBehavior: React.FunctionComponent = () => { - const [expanded, setExpanded] = React.useState(['ex2-toggle4']); + const [expanded, setExpanded] = useState(['ex2-toggle4']); - const toggle = id => { + const toggle = (id) => { const index = expanded.indexOf(id); const newExpanded: string[] = index >= 0 ? [...expanded.slice(0, index), ...expanded.slice(index + 1, expanded.length)] : [...expanded, id]; @@ -13,57 +13,50 @@ export const AccordionFixedWithMultipleExpandBehavior: React.FunctionComponent = return ( - - toggle('ex2-toggle1')} - isExpanded={expanded.includes('ex2-toggle1')} - id="ex2-toggle1" - > + + toggle('ex2-toggle1')} id="ex2-toggle1"> Item one - +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    - - toggle('ex2-toggle2')} - isExpanded={expanded.includes('ex2-toggle2')} - id="ex2-toggle2" - > + + toggle('ex2-toggle2')} id="ex2-toggle2"> Item two - +

    Vivamus et tortor sed arcu congue vehicula eget et diam. Praesent nec dictum lorem. Aliquam id diam ultrices, faucibus erat id, maximus nunc.

    - - toggle('ex2-toggle3')} - isExpanded={expanded.includes('ex2-toggle3')} - id="ex2-toggle3" - > + + toggle('ex2-toggle3')} id="ex2-toggle3"> Item three - +

    Morbi vitae urna quis nunc convallis hendrerit. Aliquam congue orci quis ultricies tempus.

    - - toggle('ex2-toggle4')} - isExpanded={expanded.includes('ex2-toggle4')} - id="ex2-toggle4" - > + + toggle('ex2-toggle4')} id="ex2-toggle4"> Item four - + +

    + Donec vel posuere orci. Phasellus quis tortor a ex hendrerit efficitur. Aliquam lacinia ligula pharetra, + sagittis ex ut, pellentesque diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere + cubilia Curae; Vestibulum ultricies nulla nibh. Etiam vel dui fermentum ligula ullamcorper eleifend non quis + tortor. Morbi tempus ornare tempus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur + ridiculus mus. Mauris et velit neque. Donec ultricies condimentum mauris, pellentesque imperdiet libero + convallis convallis. Aliquam erat volutpat. Donec rutrum semper tempus. Proin dictum imperdiet nibh, quis + dapibus nulla. Integer sed tincidunt lectus, sit amet auctor eros. +

    Donec vel posuere orci. Phasellus quis tortor a ex hendrerit efficitur. Aliquam lacinia ligula pharetra, sagittis ex ut, pellentesque diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere @@ -75,15 +68,11 @@ export const AccordionFixedWithMultipleExpandBehavior: React.FunctionComponent =

    - - toggle('ex2-toggle5')} - isExpanded={expanded.includes('ex2-toggle5')} - id="ex2-toggle5" - > + + toggle('ex2-toggle5')} id="ex2-toggle5"> Item five - +

    Vivamus finibus dictum ex id ultrices. Mauris dictum neque a iaculis blandit.

    diff --git a/packages/react-core/src/components/Accordion/examples/AccordionSingleExpandBehavior.tsx b/packages/react-core/src/components/Accordion/examples/AccordionSingleExpandBehavior.tsx index 332282c6811..64e4755485a 100644 --- a/packages/react-core/src/components/Accordion/examples/AccordionSingleExpandBehavior.tsx +++ b/packages/react-core/src/components/Accordion/examples/AccordionSingleExpandBehavior.tsx @@ -1,8 +1,8 @@ -import React from 'react'; +import { useState } from 'react'; import { Accordion, AccordionItem, AccordionContent, AccordionToggle } from '@patternfly/react-core'; export const AccordionSingleExpandBehavior: React.FunctionComponent = () => { - const [expanded, setExpanded] = React.useState('ex-toggle2'); + const [expanded, setExpanded] = useState('ex-toggle2'); const onToggle = (id: string) => { if (id === expanded) { @@ -14,17 +14,16 @@ export const AccordionSingleExpandBehavior: React.FunctionComponent = () => { return ( - + { onToggle('ex-toggle1'); }} - isExpanded={expanded === 'ex-toggle1'} id="ex-toggle1" > Item one - +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. @@ -32,17 +31,16 @@ export const AccordionSingleExpandBehavior: React.FunctionComponent = () => { - + { onToggle('ex-toggle2'); }} - isExpanded={expanded === 'ex-toggle2'} id="ex-toggle2" > Item two - +

    Vivamus et tortor sed arcu congue vehicula eget et diam. Praesent nec dictum lorem. Aliquam id diam ultrices, faucibus erat id, maximus nunc. @@ -50,32 +48,30 @@ export const AccordionSingleExpandBehavior: React.FunctionComponent = () => { - + { onToggle('ex-toggle3'); }} - isExpanded={expanded === 'ex-toggle3'} id="ex-toggle3" > Item three - +

    Morbi vitae urna quis nunc convallis hendrerit. Aliquam congue orci quis ultricies tempus.

    - + { onToggle('ex-toggle4'); }} - isExpanded={expanded === 'ex-toggle4'} id="ex-toggle4" > Item four - +

    Donec vel posuere orci. Phasellus quis tortor a ex hendrerit efficitur. Aliquam lacinia ligula pharetra, sagittis ex ut, pellentesque diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere @@ -88,17 +84,16 @@ export const AccordionSingleExpandBehavior: React.FunctionComponent = () => { - + { onToggle('ex-toggle5'); }} - isExpanded={expanded === 'ex-toggle5'} id="ex-toggle5" > Item five - +

    Vivamus finibus dictum ex id ultrices. Mauris dictum neque a iaculis blandit.

    diff --git a/packages/react-core/src/components/Accordion/examples/AccordionToggleIconAtStart.tsx b/packages/react-core/src/components/Accordion/examples/AccordionToggleIconAtStart.tsx new file mode 100644 index 00000000000..9519d2a8870 --- /dev/null +++ b/packages/react-core/src/components/Accordion/examples/AccordionToggleIconAtStart.tsx @@ -0,0 +1,102 @@ +import { useState } from 'react'; +import { Accordion, AccordionItem, AccordionContent, AccordionToggle } from '@patternfly/react-core'; + +export const AccordionToggleIconAtStart: React.FunctionComponent = () => { + const [expanded, setExpanded] = useState('start-toggle-toggle2'); + + const onToggle = (id: string) => { + if (id === expanded) { + setExpanded(''); + } else { + setExpanded(id); + } + }; + + return ( + + + { + onToggle('start-toggle-toggle1'); + }} + id="start-toggle-toggle1" + > + Item one + + +

    + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. +

    +
    +
    + + + { + onToggle('start-toggle-toggle2'); + }} + id="start-toggle-toggle2" + > + Item two + + +

    + Vivamus et tortor sed arcu congue vehicula eget et diam. Praesent nec dictum lorem. Aliquam id diam + ultrices, faucibus erat id, maximus nunc. +

    +
    +
    + + + { + onToggle('start-toggle-toggle3'); + }} + id="start-toggle-toggle3" + > + Item three + + +

    Morbi vitae urna quis nunc convallis hendrerit. Aliquam congue orci quis ultricies tempus.

    +
    +
    + + + { + onToggle('start-toggle-toggle4'); + }} + id="start-toggle-toggle4" + > + Item four + + +

    + Donec vel posuere orci. Phasellus quis tortor a ex hendrerit efficitur. Aliquam lacinia ligula pharetra, + sagittis ex ut, pellentesque diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere + cubilia Curae; Vestibulum ultricies nulla nibh. Etiam vel dui fermentum ligula ullamcorper eleifend non quis + tortor. Morbi tempus ornare tempus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur + ridiculus mus. Mauris et velit neque. Donec ultricies condimentum mauris, pellentesque imperdiet libero + convallis convallis. Aliquam erat volutpat. Donec rutrum semper tempus. Proin dictum imperdiet nibh, quis + dapibus nulla. Integer sed tincidunt lectus, sit amet auctor eros. +

    +
    +
    + + + { + onToggle('start-toggle-toggle5'); + }} + id="start-toggle-toggle5" + > + Item five + + +

    Vivamus finibus dictum ex id ultrices. Mauris dictum neque a iaculis blandit.

    +
    +
    +
    + ); +}; diff --git a/packages/react-core/src/components/Accordion/index.ts b/packages/react-core/src/components/Accordion/index.ts index 9de92992fa2..d8781e15bb3 100644 --- a/packages/react-core/src/components/Accordion/index.ts +++ b/packages/react-core/src/components/Accordion/index.ts @@ -1,5 +1,5 @@ export * from './Accordion'; export * from './AccordionContent'; -export * from './AccordionExpandedContentBody'; +export * from './AccordionExpandableContentBody'; export * from './AccordionItem'; export * from './AccordionToggle'; diff --git a/packages/react-core/src/components/ActionList/ActionList.tsx b/packages/react-core/src/components/ActionList/ActionList.tsx index 329e9c9107c..00cbf747c44 100644 --- a/packages/react-core/src/components/ActionList/ActionList.tsx +++ b/packages/react-core/src/components/ActionList/ActionList.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/ActionList/action-list'; @@ -9,15 +8,26 @@ export interface ActionListProps extends React.HTMLProps { isIconList?: boolean; /** Additional classes added to the action list */ className?: string; + /** @beta Whether the layout of children is vertical or horizontal. */ + isVertical?: boolean; } export const ActionList: React.FunctionComponent = ({ children, isIconList, - className = '', + className, + isVertical = false, ...props }: ActionListProps) => ( -
    +
    {children}
    ); diff --git a/packages/react-core/src/components/ActionList/ActionListGroup.tsx b/packages/react-core/src/components/ActionList/ActionListGroup.tsx index fd1c8214ee7..8e5a22cb3b0 100644 --- a/packages/react-core/src/components/ActionList/ActionListGroup.tsx +++ b/packages/react-core/src/components/ActionList/ActionListGroup.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/ActionList/action-list'; @@ -7,14 +6,17 @@ export interface ActionListGroupProps extends React.HTMLProps { children?: React.ReactNode; /** Additional classes added to the action list group */ className?: string; + /** Flag indicating the action list group contains multiple icons and item padding should be removed */ + isIconGroup?: boolean; } export const ActionListGroup: React.FunctionComponent = ({ children, - className = '', + className, + isIconGroup, ...props }: ActionListGroupProps) => ( -
    +
    {children}
    ); diff --git a/packages/react-core/src/components/ActionList/ActionListItem.tsx b/packages/react-core/src/components/ActionList/ActionListItem.tsx index ac796de70fc..d6827ff3801 100644 --- a/packages/react-core/src/components/ActionList/ActionListItem.tsx +++ b/packages/react-core/src/components/ActionList/ActionListItem.tsx @@ -1,5 +1,5 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/ActionList/action-list'; export interface ActionListItemProps extends React.HTMLProps { /** Children of the action list item */ @@ -10,10 +10,10 @@ export interface ActionListItemProps extends React.HTMLProps { export const ActionListItem: React.FunctionComponent = ({ children, - className = '', + className, ...props }: ActionListItemProps) => ( -
    +
    {children}
    ); diff --git a/packages/react-core/src/components/ActionList/__tests__/ActionList.test.tsx b/packages/react-core/src/components/ActionList/__tests__/ActionList.test.tsx index 4761d91643f..5bb4d943fdb 100644 --- a/packages/react-core/src/components/ActionList/__tests__/ActionList.test.tsx +++ b/packages/react-core/src/components/ActionList/__tests__/ActionList.test.tsx @@ -1,14 +1,61 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { ActionList } from '../ActionList'; +import styles from '@patternfly/react-styles/css/components/ActionList/action-list'; -describe('action list', () => { - test('renders successfully', () => { - const view = mount(test); - expect(view).toMatchSnapshot(); - }); - test('isIconList flag adds modifier', () => { - const view = mount(test); - expect(view).toMatchSnapshot(); - }); +test('Renders without children', () => { + render(); + expect(screen.getByTestId('action-list')).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with class ${styles.actionList}`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.actionList); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Does not render with class ${styles.modifiers.icons} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).not.toHaveClass(styles.modifiers.icons); +}); + +test(`Renders with class ${styles.modifiers.icons} when isIconList is true`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.icons); +}); + +test(`Does not render with class ${styles.modifiers.vertical} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).not.toHaveClass(styles.modifiers.vertical); +}); + +test(`Renders with class ${styles.modifiers.vertical} when isVertical is true`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.vertical); +}); + +test('Renders with inherited element props spread to the component', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(test); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/ActionList/__tests__/ActionListGroup.test.tsx b/packages/react-core/src/components/ActionList/__tests__/ActionListGroup.test.tsx index 925dfe719cd..66a2c8fcb25 100644 --- a/packages/react-core/src/components/ActionList/__tests__/ActionListGroup.test.tsx +++ b/packages/react-core/src/components/ActionList/__tests__/ActionListGroup.test.tsx @@ -1,10 +1,43 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { ActionListGroup } from '../ActionListGroup'; +import styles from '@patternfly/react-styles/css/components/ActionList/action-list'; -describe('action list group', () => { - test('renders successfully', () => { - const view = mount(test); - expect(view).toMatchSnapshot(); - }); +test('Renders without children', () => { + render(); + expect(screen.getByTestId('action-list-group')).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with only class ${styles.actionListGroup} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.actionListGroup, { exact: true }); +}); + +test(`Renders with class ${styles.modifiers.icons} when isIconGroup is true`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.icons); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders with inherited element props spread to the component', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(test); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/ActionList/__tests__/ActionListItem.test.tsx b/packages/react-core/src/components/ActionList/__tests__/ActionListItem.test.tsx index a5284478ab6..6c14466d16c 100644 --- a/packages/react-core/src/components/ActionList/__tests__/ActionListItem.test.tsx +++ b/packages/react-core/src/components/ActionList/__tests__/ActionListItem.test.tsx @@ -1,10 +1,37 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { ActionListItem } from '../ActionListItem'; +import styles from '@patternfly/react-styles/css/components/ActionList/action-list'; -describe('action list item', () => { - test('renders successfully', () => { - const view = mount(test); - expect(view).toMatchSnapshot(); - }); +test('Renders without children', () => { + render(); + expect(screen.getByTestId('action-list-item')).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with class ${styles.actionList}__item`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(`${styles.actionList}__item`); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders with inherited element props spread to the component', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(test); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionList.test.tsx.snap b/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionList.test.tsx.snap index 8972715bdc9..79a8ada2972 100644 --- a/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionList.test.tsx.snap +++ b/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionList.test.tsx.snap @@ -1,23 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`action list isIconList flag adds modifier 1`] = ` - +exports[`Matches the snapshot 1`] = ` +
    test
    -
    -`; - -exports[`action list renders successfully 1`] = ` - -
    - test -
    -
    + `; diff --git a/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListGroup.test.tsx.snap b/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListGroup.test.tsx.snap index bcfa4682ff3..e4a83694b0c 100644 --- a/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListGroup.test.tsx.snap +++ b/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListGroup.test.tsx.snap @@ -1,11 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`action list group renders successfully 1`] = ` - +exports[`Matches the snapshot 1`] = ` +
    test
    -
    + `; diff --git a/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListItem.test.tsx.snap b/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListItem.test.tsx.snap index 83588009eb5..db634495ba7 100644 --- a/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListItem.test.tsx.snap +++ b/packages/react-core/src/components/ActionList/__tests__/__snapshots__/ActionListItem.test.tsx.snap @@ -1,11 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`action list item renders successfully 1`] = ` - +exports[`Matches the snapshot 1`] = ` +
    test
    -
    + `; diff --git a/packages/react-core/src/components/ActionList/examples/ActionList.md b/packages/react-core/src/components/ActionList/examples/ActionList.md index c3efc39c11d..bf6d0e14a3e 100644 --- a/packages/react-core/src/components/ActionList/examples/ActionList.md +++ b/packages/react-core/src/components/ActionList/examples/ActionList.md @@ -1,31 +1,43 @@ --- id: Action list section: components -cssPrefix: pf-c-action-list +cssPrefix: pf-v6-c-action-list propComponents: ['ActionList', 'ActionListGroup', 'ActionListItem'] --- -import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon'; +import { Fragment, useState } from 'react'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/js/icons/rh-microns-close-icon'; import CheckIcon from '@patternfly/react-icons/dist/js/icons/check-icon'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; ## Examples ### Action list single group ```ts file="ActionListSingleGroup.tsx" + ``` ### Action list with icons ```ts file="./ActionListWithIcons.tsx" + ``` ### Action list multiple groups ```ts file="./ActionListMultipleGroups.tsx" + ``` ### Action list with cancel button ```ts file="./ActionListWithCancelButton.tsx" + +``` + +### Vertical action list + +```ts file="./ActionListVertical.tsx" isBeta + ``` diff --git a/packages/react-core/src/components/ActionList/examples/ActionListMultipleGroups.tsx b/packages/react-core/src/components/ActionList/examples/ActionListMultipleGroups.tsx index 0cbd8942fd5..b9f3ecec657 100644 --- a/packages/react-core/src/components/ActionList/examples/ActionListMultipleGroups.tsx +++ b/packages/react-core/src/components/ActionList/examples/ActionListMultipleGroups.tsx @@ -1,28 +1,27 @@ -import React from 'react'; import { ActionList, ActionListGroup, ActionListItem, Button } from '@patternfly/react-core'; export const ActionListMultipleGroups: React.FunctionComponent = () => ( - - - - diff --git a/packages/react-core/src/components/ActionList/examples/ActionListSingleGroup.tsx b/packages/react-core/src/components/ActionList/examples/ActionListSingleGroup.tsx index 0d022998b0f..75fa07880a8 100644 --- a/packages/react-core/src/components/ActionList/examples/ActionListSingleGroup.tsx +++ b/packages/react-core/src/components/ActionList/examples/ActionListSingleGroup.tsx @@ -1,86 +1,100 @@ -import React from 'react'; +import { Fragment, useState } from 'react'; import { ActionList, + ActionListGroup, ActionListItem, Button, Dropdown, + DropdownList, DropdownItem, - DropdownSeparator, - KebabToggle + MenuToggle, + MenuToggleElement, + Divider } from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; export const ActionListSingleGroup: React.FunctionComponent = () => { - const [isOpen, setIsOpen] = React.useState(false); + const [isOpen, setIsOpen] = useState(false); - const onToggle = ( - isOpen: boolean, - event: MouseEvent | TouchEvent | KeyboardEvent | React.KeyboardEvent | React.MouseEvent - ) => { - event.stopPropagation(); - setIsOpen(isOpen); + const onToggle = () => { + setIsOpen(!isOpen); }; - const onSelect = (event: React.SyntheticEvent) => { - event.stopPropagation(); + const onSelect = (event: React.MouseEvent | undefined) => { + event?.stopPropagation(); setIsOpen(!isOpen); }; - const dropdownItems = [ - Link, - - Action - , - - Disabled Link - , - - Disabled Action - , - , - Separated Link, - - Separated Action - - ]; - + const dropdownItems = ( + <> + + Link + + Action + + Disabled Link + + + Disabled Action + + + + Separated Link + + Separated Action + + ); return ( - + - - - - - - + + + + + + + +
    With kebab - - - - - - - - } - isOpen={isOpen} - isPlain - dropdownItems={dropdownItems} - position="right" - /> - + + + + + + + + + ) => ( + } + /> + )} + isOpen={isOpen} + onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)} + > + {dropdownItems} + + + -
    + ); }; diff --git a/packages/react-core/src/components/ActionList/examples/ActionListVertical.tsx b/packages/react-core/src/components/ActionList/examples/ActionListVertical.tsx new file mode 100644 index 00000000000..c2dfbadd1f9 --- /dev/null +++ b/packages/react-core/src/components/ActionList/examples/ActionListVertical.tsx @@ -0,0 +1,46 @@ +import { ActionList, ActionListGroup, ActionListItem, Button } from '@patternfly/react-core'; +import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; + +export const ActionListVertical: React.FunctionComponent = () => ( + <> +

    Multiple groups

    + + + + + + + + + + + + + + + + + + +

    Icons, in two groups

    + + + + - - - - + + + + + + + +
    In wizards - - - - + ); diff --git a/packages/react-core/src/components/ActionList/examples/ActionListWithIcons.tsx b/packages/react-core/src/components/ActionList/examples/ActionListWithIcons.tsx index 216ddb0dca9..5da11ed9b34 100644 --- a/packages/react-core/src/components/ActionList/examples/ActionListWithIcons.tsx +++ b/packages/react-core/src/components/ActionList/examples/ActionListWithIcons.tsx @@ -1,19 +1,62 @@ -import React from 'react'; -import { ActionList, ActionListItem, Button } from '@patternfly/react-core'; -import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; +import { ActionList, ActionListGroup, ActionListItem, Button } from '@patternfly/react-core'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon'; export const ActionListWithIcons: React.FunctionComponent = () => ( - - - - - - - - + <> +

    With list icons wrapper

    + + + - )} - -); +}: AlertActionCloseButtonProps) => { + const closeButtonRef = useRef(null); + const { hasAnimations, updateTransitionEnd } = useContext(AlertGroupContext); + const { offstageRight } = alertGroupStyles.modifiers; + + const getParentAlertGroupItem = () => closeButtonRef.current?.closest(`.${alertGroupStyles.alertGroupItem}`); + const handleOnClick = () => { + if (hasAnimations) { + getParentAlertGroupItem()?.classList.add(offstageRight); + updateTransitionEnd(onClose); + } else { + onClose(); + } + }; + + return ( + + {({ title, variantLabel: alertVariantLabel }) => ( + + + )} + + + ); +}; + +AlertGroupInline.displayName = 'AlertGroupInline'; diff --git a/packages/react-core/src/components/Alert/AlertIcon.tsx b/packages/react-core/src/components/Alert/AlertIcon.tsx index eb8e1e04cf3..285b09cafe8 100644 --- a/packages/react-core/src/components/Alert/AlertIcon.tsx +++ b/packages/react-core/src/components/Alert/AlertIcon.tsx @@ -1,34 +1,33 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Alert/alert'; -import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon'; -import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon'; -import ExclamationTriangleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon'; -import InfoCircleIcon from '@patternfly/react-icons/dist/esm/icons/info-circle-icon'; -import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; +import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; +import RhUiErrorFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-error-fill-icon'; +import RhUiWarningFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-warning-fill-icon'; +import RhUiInformationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-information-fill-icon'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; export const variantIcons = { - success: CheckCircleIcon, - danger: ExclamationCircleIcon, - warning: ExclamationTriangleIcon, - info: InfoCircleIcon, - default: BellIcon + success: RhUiCheckCircleFillIcon, + danger: RhUiErrorFillIcon, + warning: RhUiWarningFillIcon, + info: RhUiInformationFillIcon, + custom: RhUiNotificationFillIcon }; export interface AlertIconProps extends React.HTMLProps { - /** variant */ - variant: 'success' | 'danger' | 'warning' | 'info' | 'default'; - /** className */ + /** Additional class names added to the alert icon. */ className?: string; - /** A custom icon. If not set the icon is set according to the variant */ + /** A custom icon. If not set the icon is set according to the variant. */ customIcon?: React.ReactNode; + /** Variant of the alert icon. */ + variant: 'success' | 'danger' | 'warning' | 'info' | 'custom'; } export const AlertIcon = ({ variant, customIcon, className = '', ...props }: AlertIconProps) => { const Icon = variantIcons[variant]; - return ( + return Icon ? (
    {customIcon || }
    - ); + ) : null; }; diff --git a/packages/react-core/src/components/Alert/AlertToggleExpandButton.tsx b/packages/react-core/src/components/Alert/AlertToggleExpandButton.tsx index 842d0fdfb27..2e7c7c030a7 100644 --- a/packages/react-core/src/components/Alert/AlertToggleExpandButton.tsx +++ b/packages/react-core/src/components/Alert/AlertToggleExpandButton.tsx @@ -1,29 +1,29 @@ -import * as React from 'react'; +import { useContext } from 'react'; import { Button, ButtonProps, ButtonVariant } from '../Button'; import { AlertContext } from './AlertContext'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Alert/alert'; export interface AlertToggleExpandButtonProps extends ButtonProps { - /** Aria label for the toggle button */ + /** Accessible label for the toggle button. */ 'aria-label'?: string; - /** A callback for when the toggle button is clicked */ - onToggleExpand?: () => void; - /** Flag to indicate if the content is expanded */ + /** Flag to indicate if the content is expanded. */ isExpanded?: boolean; - /** Variant label for the toggle button */ + /** A callback for when the toggle button is clicked. */ + onToggleExpand?: () => void; + /** Variant label for the toggle button. */ variantLabel?: string; } export const AlertToggleExpandButton: React.FunctionComponent = ({ - 'aria-label': ariaLabel, + 'aria-label': ariaLabel = '', variantLabel, onToggleExpand, - isExpanded, + isExpanded = false, ...props }: AlertToggleExpandButtonProps) => { - const { title, variantLabel: alertVariantLabel } = React.useContext(AlertContext); + const { title, variantLabel: alertVariantLabel } = useContext(AlertContext); return ( + icon={ + + + + } + /> ); }; AlertToggleExpandButton.displayName = 'AlertToggleExpandButton'; diff --git a/packages/react-core/src/components/Alert/__tests__/Alert.test.tsx b/packages/react-core/src/components/Alert/__tests__/Alert.test.tsx index 27a8eae0821..19b394af444 100644 --- a/packages/react-core/src/components/Alert/__tests__/Alert.test.tsx +++ b/packages/react-core/src/components/Alert/__tests__/Alert.test.tsx @@ -1,196 +1,733 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { act, useContext } from 'react'; import { Alert, AlertVariant } from '../Alert'; -import { AlertActionLink } from '../AlertActionLink'; -import { AlertActionCloseButton } from '../AlertActionCloseButton'; -import { UsersIcon } from '@patternfly/react-icons'; - -test('default Alert variant is default', () => { - const view = mount(Alert testing); - expect( - view - .find('Alert') - .childAt(0) - .prop('className') - ).toContain('pf-c-alert'); -}); - -Object.values(AlertVariant).forEach(variant => { - describe(`Alert - ${variant}`, () => { - test('Description', () => { - const view = mount( - - Some alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('Title', () => { - const view = mount( - - Some alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('Heading level', () => { - const view = mount( - - Some alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('Action Link', () => { - const view = mount( - test]} title=""> - Some alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('Action Close Button', () => { - const onClose = jest.fn(); - const view = mount( - } - title={`Sample ${variant} alert`} - > - Some alert - - ); - expect(view).toMatchSnapshot(); - view.find('button[aria-label="Close"]').simulate('click'); - expect(onClose).toHaveBeenCalled(); - }); - - test('Action and Title', () => { - const view = mount( - test]} title="Some title"> - Some alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('Custom aria label', () => { - const view = mount( - test]} - title="Some title" - > - Some alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('inline variation', () => { - const view = mount( - - Some alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('expandable variation', () => { - const view = mount( - -

    Success alert description. This should tell the user more information about the alert.

    -
    - ) - expect(view).toMatchSnapshot(); - }) - - test('expandable variation description hidden', () => { - const wrapper = mount( - -

    Success alert description. This should tell the user more information about the alert.

    -
    - ) - const descriptionExists = wrapper.find('.pf-c-alert__description').exists(); - expect(descriptionExists).toBeFalsy(); - }) - - test('Toast alerts match snapsnot', () => { - const view = mount( - - Some toast alert - - ); - expect(view).toMatchSnapshot(); - }); - - test('Toast alerts contain default live region', () => { - const wrapper = mount( - - Some toast alert - - ); - const liveRegion = wrapper.find({ 'aria-live': 'polite' }).length; - expect(liveRegion).toBe(1); - }); - - test('Toast alert live regions are not atomic', () => { - const wrapper = mount( - - Some toast alert - - ); - expect(wrapper.find('.pf-c-alert').prop('aria-atomic')).toBe('false'); - }); - - test('Non-toast alerts can have custom live region settings', () => { - const wrapper = mount( - - Some noisy alert - - ); - const alert = wrapper.find(Alert); - - expect(alert.prop('aria-live')).toBe('assertive'); - expect(alert.prop('aria-relevant')).toBe('all'); - expect(alert.prop('aria-atomic')).toBe('true'); - }); - - test('Custom icon', () => { - const view = mount( - } - variant={variant} - aria-label={`${variant} custom icon alert`} - title="custom icon alert title" - > - Some noisy alert - +import { AlertContext } from '../AlertContext'; +import { capitalize } from '../../../helpers'; +import cssAlertTitleMaxLines from '@patternfly/react-tokens/dist/esm/c_alert__title_max_lines'; +import styles from '@patternfly/react-styles/css/components/Alert/alert'; + +jest.mock('../AlertToggleExpandButton', () => ({ + AlertToggleExpandButton: ({ isExpanded, onToggleExpand, ...props }) => ( + + ) +})); + +jest.mock('../AlertIcon', () => ({ + AlertIcon: ({ variant, className, customIcon, ...props }) => ( +
    +

    custom icon: {customIcon}

    +

    variant: {variant}

    +
    + ) +})); + +test('Renders without children', () => { + render( +
    + +
    + ); + + expect(screen.getByTestId('container').firstChild).toBeVisible(); +}); + +test(`Renders with class ${styles.alert} on the containing div`, () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).toHaveClass(styles.alert); +}); + +test(`Renders with class ${styles.alertTitle} on the div containing the title`, () => { + render(Some alert); + expect(screen.getByRole('heading', { name: 'Custom alert: Some title' })).toHaveClass(styles.alertTitle); +}); + +test('Renders with Custom hidden text of "Custom alert:"', () => { + render(Some alert); + expect(screen.getByText('Custom alert:')).toBeInTheDocument(); +}); + +['success', 'danger', 'warning', 'info'].forEach((variant) => { + test(`Does not render with class pf-m-${variant} by default`, () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).not.toHaveClass(`pf-m-${variant}`); + }); + + test(`Renders with class pf-m-${variant} when variant = ${variant}`, () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).toHaveClass(`pf-m-${variant}`); + }); + + test(`Renders with hidden text "${capitalize(variant)} alert:" when variant = ${variant}`, () => { + render( + + Some alert + + ); + expect(screen.getByText(`${capitalize(variant)} alert:`)).toBeInTheDocument(); + }); + + test(`Renders the title with an accessible name of '${capitalize( + variant + )} alert: Some title' when variant = ${variant}`, () => { + render( + + Some alert + + ); + + expect(screen.getByRole('heading')).toHaveAccessibleName(`${capitalize(variant)} alert: Some title`); + }); + + test(`Passes AlertToggleExpandButton an aria label of '${capitalize( + variant + )} alert details' when variant = ${variant} and it is expandable`, () => { + render( + + Some alert + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName(`${capitalize(variant)} alert details`); + }); + + test(`Provides a variantLabel of '${capitalize(variant)} alert:' in a context when variant = ${variant}`, () => { + const TestComponent: React.FunctionComponent = () => { + const context = useContext(AlertContext); + + return ( +

    + {context.title} +

    ); - expect(view).toMatchSnapshot(); - }); + }; + + render( + } + > + Some alert + + ); + + expect(screen.getByTestId('Test-component')).toHaveAccessibleName(`${capitalize(variant)} alert:`); + }); +}); + +test('Does not render with class pf-m-inline by default', () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).not.toHaveClass('pf-m-inline'); +}); + +test('Renders with class pf-m-inline when isInline = true', () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).toHaveClass('pf-m-inline'); +}); + +test('Does not render with class pf-m-plain by default', () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).not.toHaveClass('pf-m-plain'); +}); + +test('Renders with class pf-m-plain when isPlain = true', () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).toHaveClass('pf-m-plain'); +}); + +test('Renders the title', () => { + render(Some alert); + + expect(screen.getByText('Some title')).toBeVisible(); +}); + +test('Renders the title as an h4 by default', () => { + render(Some alert); + + expect(screen.getByRole('heading', { level: 4, name: 'Custom alert: Some title' })).toBeVisible(); +}); + +test('Renders the title as other heading levels when one is passed using component', () => { + render( + + Some alert + + ); + + expect(screen.getByRole('heading', { level: 1, name: 'Custom alert: Some title' })).toBeVisible(); +}); + +test('Renders the element passed via the actionClose prop', () => { + render( + Action close}> + Some alert + + ); + + expect(screen.getByRole('button', { name: 'Action close' })).toBeVisible(); +}); + +test(`Renders the actionClose element inside ${styles.alertAction}`, () => { + render( + + Some alert + + ); + + expect(screen.getByText('Action close')).toHaveClass(styles.alertAction); +}); + +test('Provides the actionClose element access to the title via a context', () => { + const TestComponent: React.FunctionComponent = () => { + const context = useContext(AlertContext); + + return ( +

    + {context.title} +

    + ); + }; + + render( + }> + Some alert + + ); + + expect(screen.getByTestId('Test-component')).toHaveTextContent('Some title'); +}); + +test('Renders the element passed via the actionLinks prop', () => { + render( + Action link}> + Some alert + + ); + + expect(screen.getByRole('button', { name: 'Action link' })).toBeVisible(); +}); + +test(`Renders the actionLinks element inside ${styles.alertActionGroup}`, () => { + render( + + Some alert + + ); + + expect(screen.getByText('Action link')).toHaveClass(styles.alertActionGroup); +}); + +test('Renders children', () => { + render(Some alert); + + expect(screen.getByText('Some alert')).toBeVisible(); +}); + +test(`Renders children inside ${styles.alertDescription}`, () => { + render(Some alert); + + expect(screen.getByText('Some alert')).toHaveClass(styles.alertDescription); +}); + +test('Renders with the aria label passed via prop', () => { + render( + + Some alert + + ); + + expect(screen.getByTestId('Alert-test-id')).toHaveAccessibleName('Test label'); +}); + +test('Renders with the variantLabel passed via prop', () => { + const TestComponent: React.FunctionComponent = () => { + const context = useContext(AlertContext); + + return ( +

    + {context.title} +

    + ); + }; + + render( + }> + Some alert + + ); + + expect(screen.getByTestId('Test-component')).toHaveAccessibleName('Test label'); +}); + +test('Renders without aria-live and aria-atomic attributes by default', () => { + render( + + Some alert + + ); + + const alertContainer = screen.getByTestId('Alert-test-id'); + + expect(alertContainer).not.toHaveAttribute('aria-live'); + expect(alertContainer).not.toHaveAttribute('aria-atomic'); +}); + +test('Has an aria-live value of polite and aria-atomic value of false when isLiveRegion = true', () => { + render( + + Some alert + + ); + + const alertContainer = screen.getByTestId('Alert-test-id'); + + expect(alertContainer).toHaveAttribute('aria-live', 'polite'); + expect(alertContainer).toHaveAttribute('aria-atomic', 'false'); +}); + +test('Renders with no timeout by default', () => { + jest.useFakeTimers(); + + render(Some alert); + + act(() => { + jest.advanceTimersByTime(8000); }); + + expect(screen.getByText('Some alert')).toBeVisible(); + jest.useRealTimers(); }); +test('Removes the alert after 8000ms when timeout = true', () => { + jest.useFakeTimers(); + + render( + + Some alert + + ); + + act(() => { + jest.advanceTimersByTime(7999); + }); + + expect(screen.getByText('Some alert')).toBeVisible(); + + act(() => { + jest.advanceTimersByTime(1); + }); + + expect(screen.queryByText('Some alert')).not.toBeInTheDocument(); + jest.useRealTimers(); +}); + +test('Removes the alert after a custom time when timeout is passed with a number', () => { + jest.useFakeTimers(); + + render( + + Some alert + + ); + + act(() => { + jest.advanceTimersByTime(1999); + }); + + expect(screen.getByText('Some alert')).toBeVisible(); + + act(() => { + jest.advanceTimersByTime(1); + }); + + expect(screen.queryByText('Some alert')).not.toBeInTheDocument(); + jest.useRealTimers(); +}); + +test('Does not remove the alert on timeout if the user is focused on the alert', async () => { + const user = userEvent.setup({ + advanceTimers: (delay) => jest.advanceTimersByTime(delay) + }); + jest.useFakeTimers(); + + render( + + Some alert + + ); + + const alert = screen.getByText('Some alert'); + + await user.click(alert); + + act(() => { + jest.advanceTimersByTime(8000); + }); + + expect(screen.getByText('Some alert')).toBeVisible(); + jest.useRealTimers(); +}); + +test('Does not remove the alert on timeout if the user is hovered over the alert', async () => { + const user = userEvent.setup({ + advanceTimers: (delay) => jest.advanceTimersByTime(delay) + }); + jest.useFakeTimers(); + + render( + + Some alert + + ); + + const alert = screen.getByText('Some alert'); + + await user.hover(alert); + + act(() => { + jest.advanceTimersByTime(8000); + }); + + expect(alert).toBeVisible(); + jest.useRealTimers(); +}); + +test('Removes the alert after the user removes focus from the alert and 3000ms have passed', async () => { + const user = userEvent.setup({ + advanceTimers: (delay) => jest.advanceTimersByTime(delay) + }); + jest.useFakeTimers(); + + render( +
    + + + Some alert + +
    + ); + + const alert = screen.getByText('Some alert'); + + await user.click(alert); + + act(() => { + jest.advanceTimersByTime(8000); + }); + + await user.click(screen.getByRole('textbox')); + + act(() => { + jest.advanceTimersByTime(3000); + }); + + expect(screen.queryByText('Some alert')).not.toBeInTheDocument(); + jest.useRealTimers(); +}); + +test('Removes the alert after the user removes hover from the alert and 3000ms have passed', async () => { + const user = userEvent.setup({ + advanceTimers: (delay) => jest.advanceTimersByTime(delay) + }); + jest.useFakeTimers(); + + render( +
    + + + Some alert + +
    + ); + + const alert = screen.getByText('Some alert'); + + await user.hover(alert); + + act(() => { + jest.advanceTimersByTime(8000); + }); + + await user.hover(screen.getByRole('textbox')); + + act(() => { + jest.advanceTimersByTime(3000); + }); + + expect(screen.queryByText('Some alert')).not.toBeInTheDocument(); + jest.useRealTimers(); +}); + +test('Removes the alert after the user removes hover from the alert and timeoutAnimation time has passed', async () => { + const user = userEvent.setup({ + advanceTimers: (delay) => jest.advanceTimersByTime(delay) + }); + jest.useFakeTimers(); + + render( +
    + + + Some alert + +
    + ); + + const alert = screen.getByText('Some alert'); + + await user.hover(alert); + + act(() => { + jest.advanceTimersByTime(8000); + }); + + await user.hover(screen.getByRole('textbox')); + + act(() => { + jest.advanceTimersByTime(1000); + }); + + expect(screen.queryByText('Some alert')).not.toBeInTheDocument(); + jest.useRealTimers(); +}); + +test('Does not call the onTimeout callback before the timeout period has expired', () => { + jest.useFakeTimers(); + const onTimeoutMock = jest.fn(); + + render( + + Some alert + + ); + + act(() => { + jest.advanceTimersByTime(7999); + }); + + expect(onTimeoutMock).not.toHaveBeenCalled(); + jest.useRealTimers(); +}); + +test('Calls the onTimeout callback after the timeout period has expired', () => { + jest.useFakeTimers(); + const onTimeoutMock = jest.fn(); + + render( + + Some alert + + ); + + act(() => { + jest.advanceTimersByTime(8000); + }); + + expect(onTimeoutMock).toHaveBeenCalledTimes(1); + jest.useRealTimers(); +}); + +test('Renders titles without truncation styling by default', () => { + render(Some alert); + + const title = screen.getByRole('heading'); + + expect(title).not.toHaveClass('pf-m-truncate'); + expect(title).not.toHaveAttribute('style'); +}); + +test('Renders titles with the expected truncation styling when truncateTitle is a value', () => { + render( + + Some alert + + ); + + const title = screen.getByRole('heading'); + + expect(title).toHaveClass('pf-m-truncate'); + expect(title).toHaveAttribute('style', `${cssAlertTitleMaxLines.name}: 3;`); +}); + +test('Passes customIcon value to AlertIcon', () => { + render( + + Some alert + + ); + + expect(screen.getByText('custom icon: custom-icon-test')).toBeVisible(); +}); + +test('Does not render with class pf-m-expandable by default', () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).not.toHaveClass('pf-m-expandable'); +}); + +test('Renders with class pf-m-expandable when isExpandable = true', () => { + render( + + Some alert + + ); + expect(screen.getByTestId('Alert-test-id')).toHaveClass('pf-m-expandable'); +}); + +test(`Renders AlertToggleExpandButton inside ${styles.alertToggle}`, () => { + render( + + Some alert + + ); + + expect(screen.getByRole('button').parentElement).toHaveClass(styles.alertToggle); +}); + +test('Does not render with class pf-m-expanded when AlertToggleExpandButton has not been clicked', () => { + render( + + Some alert + + ); + + expect(screen.getByTestId('Alert-test-id')).not.toHaveClass('pf-m-expanded'); +}); + +test('Renders with class pf-m-expanded once the AlertToggleExpandButton is clicked', async () => { + const user = userEvent.setup(); + + render( + + Some alert + + ); + + await user.click(screen.getByRole('button')); + + expect(screen.getByTestId('Alert-test-id')).toHaveClass('pf-m-expanded'); +}); + +test('Does not render children when isExpandable = true and AlertToggleExpandButton has not been clicked', () => { + render( + + Some alert + + ); + + expect(screen.queryByText('Some alert')).not.toBeInTheDocument(); +}); + +test('Renders children when isExpandable = true and AlertToggleExpandButton has been clicked', async () => { + const user = userEvent.setup(); + + render( + + Some alert + + ); + + await user.click(screen.getByRole('button')); + + expect(screen.getByText('Some alert')).toBeVisible(); +}); + +test('Passes AlertToggleExpandButton isExpanded = false when AlertToggleExpandButton has not been clicked', () => { + render( + + Some alert + + ); + + expect(screen.getByText('isExpanded: false')).toBeVisible(); +}); + +test('Passes AlertToggleExpandButton isExpanded = true once the AlertToggleExpandButton is clicked', async () => { + const user = userEvent.setup(); + + render( + + Some alert + + ); + + await user.click(screen.getByRole('button')); + + expect(screen.getByText('isExpanded: true')).toBeVisible(); +}); + +test('Passes AlertToggleExpandButton the aria label provided via toggleAriaLabel', () => { + render( + + Some alert + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Passes the id prop to the top level returned element', () => { + render( + + Some alert + + ); + + expect(screen.getByLabelText('Test label')).toHaveAttribute('id', 'test-id'); +}); + +test('Renders with inherited element props spread to the component', () => { + render( + <> + +

    Described by text

    + + ); + + expect(screen.getByLabelText('Test label')).toHaveAccessibleDescription('Described by text'); +}); -test('Alert truncate title', () => { - const view = mount(Alert testing); - expect( - view - .find('h4') - .prop('className') - ).toContain('pf-m-truncate'); +test('Matches snapshot', () => { + const { asFragment } = render( + + Some toast alert + + ); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Alert/__tests__/AlertActionCloseButton.test.tsx b/packages/react-core/src/components/Alert/__tests__/AlertActionCloseButton.test.tsx new file mode 100644 index 00000000000..804b2bd5ab0 --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/AlertActionCloseButton.test.tsx @@ -0,0 +1,131 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { AlertActionCloseButton } from '../AlertActionCloseButton'; +import { AlertGroupContext } from '../AlertGroupContext'; +import { AlertContext } from '../AlertContext'; + +jest.mock('../../Button'); + +test('Renders without children', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toBeVisible(); +}); + +test('Renders with custom class names provided via prop', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveClass('custom-class'); +}); + +test('Renders with inherited element props spread to the component', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Renders a Button with variant: ButtonVariant.plain', () => { + render( + + + + ); + + expect(screen.getByText('variant: plain')).toBeVisible(); +}); + +test('Does not call the callback provided via onClose when it is not clicked', () => { + const onCloseMock = jest.fn(); + + render( + + + + ); + + expect(onCloseMock).not.toHaveBeenCalled(); +}); + +test('Calls the callback provided via onClose when clicked', async () => { + const user = userEvent.setup(); + const onCloseMock = jest.fn(); + + render( + + + + ); + + await user.click(screen.getByRole('button')); + + expect(onCloseMock).toHaveBeenCalledTimes(1); +}); + +test('Calls updateTransitionEnd with onClose when animations are enabled', async () => { + const user = userEvent.setup(); + const onClose = jest.fn(); + const updateMock = jest.fn(); + render( + + + + + + ); + + expect(updateMock).not.toHaveBeenCalled(); + await user.click(screen.getByRole('button')); + expect(updateMock).toHaveBeenCalledWith(onClose); + expect(updateMock).toHaveBeenCalledTimes(1); +}); + +test('Renders with an aria label composed with the title and variantLabel provided via a context by default', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Close variantLabel alert: title'); +}); + +test('Renders with an aria label composed with the title provided via a context and variantLabel provided via prop', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Close variant label prop alert: title'); +}); + +test('Renders with the aria label provided via prop when one is provided', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Aria label prop'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + + + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Alert/__tests__/AlertActionLink.test.tsx b/packages/react-core/src/components/Alert/__tests__/AlertActionLink.test.tsx new file mode 100644 index 00000000000..b70ae2d4aea --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/AlertActionLink.test.tsx @@ -0,0 +1,61 @@ +import { render, screen } from '@testing-library/react'; +import { AlertActionLink } from '../AlertActionLink'; + +jest.mock('../../Button'); + +test('Renders without children', () => { + render( +
    + +
    + ); + + expect(screen.getByTestId('container').firstChild).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByRole('button')).toBeVisible(); +}); + +test('Renders ReactNode as children', () => { + render( + +
    + Learn More +
    +
    + ); + + expect(screen.getByText('Learn More')).toBeVisible(); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test); + + expect(screen.getByRole('button')).toHaveClass('custom-class'); +}); + +test('Renders with inherited element props spread to the component', () => { + render(Test); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Renders a Button with variant: ButtonVariant.link', () => { + render(Test); + + expect(screen.getByText('variant: link')).toBeVisible(); +}); + +test('Renders a Button with isInline: true', () => { + render(Test); + + expect(screen.getByText('isInline: true')).toBeVisible(); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Alert/__tests__/AlertGroup.test.tsx b/packages/react-core/src/components/Alert/__tests__/AlertGroup.test.tsx new file mode 100644 index 00000000000..03255da4a9c --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/AlertGroup.test.tsx @@ -0,0 +1,179 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { Alert } from '../../Alert'; +import { AlertGroup } from '../../Alert'; +import { AlertActionCloseButton } from '../../../components/Alert/AlertActionCloseButton'; +import { AnimationsProvider } from '../../../helpers/AnimationsProvider'; + +test('Alert Group renders without children', () => { + render( +
    + +
    + ); + + expect(screen.getByTestId('container').firstChild).toBeVisible(); + expect(screen.getByTestId('alertgroup').children.length).toBe(0); +}); + +test('Alert Group works with n children', () => { + render( + + + + + ); + expect(screen.getByTestId('container').children.length).toBe(2); +}); + +test('Alert group overflow shows up', async () => { + const overflowMessage = 'View 2 more alerts'; + const onOverflowClick = jest.fn(); + const user = userEvent.setup(); + + render( + + + + ); + + expect(screen.getAllByRole('listitem')).toHaveLength(2); + + const overflowButton = screen.getByRole('button', { name: 'View 2 more alerts' }); + expect(overflowButton).toBeInTheDocument(); + + await user.click(overflowButton); + expect(onOverflowClick).toHaveBeenCalled(); +}); + +test('Standard Alert Group is not a toast alert group', () => { + render( + + + + ); + + expect(screen.getByText('alert title').parentElement).not.toHaveClass('pf-m-toast'); +}); + +test('Toast Alert Group contains expected modifier class', async () => { + render( + + + + ); + + // Wait for the portal to be created and rendered + const alertGroup = await screen.findByLabelText('group label'); + expect(alertGroup).toHaveClass('pf-m-toast'); +}); + +test('Calls the callback set by updateTransitionEnd when transition ends and animations are enabled', async () => { + window.matchMedia = (query) => ({ + matches: false, + media: query, + onchange: null, + addListener: () => {}, // deprecated + removeListener: () => {}, // deprecated + addEventListener: () => {}, + removeEventListener: () => {}, + dispatchEvent: () => true + }); + const mockCallback = jest.fn(); + const user = userEvent.setup(); + + render( + + } + /> + + ); + + const closeButton = await screen.findByLabelText('Close'); + await user.click(closeButton); + expect(mockCallback).not.toHaveBeenCalled(); + // fireEvent is needed here because transitionEnd is a browser event that occurs automatically + // when CSS transitions complete, not a user interaction that userEvent can simulate + fireEvent.transitionEnd(screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item') as HTMLElement); + expect(mockCallback).toHaveBeenCalled(); +}); + +test('Does not call the callback set by updateTransitionEnd when transition ends and animations are disabled', async () => { + window.matchMedia = (query) => ({ + matches: false, + media: query, + onchange: null, + addListener: () => {}, // deprecated + removeListener: () => {}, // deprecated + addEventListener: () => {}, + removeEventListener: () => {}, + dispatchEvent: () => true + }); + const mockCallback = jest.fn(); + const user = userEvent.setup(); + + render( + + } + /> + + ); + + const closeButton = await screen.findByLabelText('Close'); + await user.click(closeButton); + expect(mockCallback).toHaveBeenCalledTimes(1); + // The transitionend event firing should not cause the callback to be called again + // fireEvent is needed here because transitionEnd is a browser event that occurs automatically + // when CSS transitions complete, not a user interaction that userEvent can simulate + fireEvent.transitionEnd(screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item') as HTMLElement); + expect(mockCallback).toHaveBeenCalledTimes(1); +}); + +describe('Animation context behavior', () => { + test('respects AnimationsProvider context when no local hasAnimations prop', () => { + render( + + + + + + ); + + // Should apply animation class when animations are enabled via context + const alertGroupItem = screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item'); + expect(alertGroupItem).toHaveClass('pf-m-offstage-top'); + }); + + test('local hasAnimations prop takes precedence over context', () => { + render( + + + + + + ); + + // Should not apply animation class when local hasAnimations=false overrides context + const alertGroupItem = screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item'); + expect(alertGroupItem).not.toHaveClass('pf-m-offstage-top'); + }); + + test('works without AnimationsProvider (backward compatibility)', () => { + render( + + + + ); + + // Should not apply animation class when no context and no local hasAnimations + const alertGroupItem = screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item'); + expect(alertGroupItem).not.toHaveClass('pf-m-offstage-top'); + }); +}); diff --git a/packages/react-core/src/components/Alert/__tests__/AlertIcon.test.tsx b/packages/react-core/src/components/Alert/__tests__/AlertIcon.test.tsx new file mode 100644 index 00000000000..7dea0f0ce8a --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/AlertIcon.test.tsx @@ -0,0 +1,84 @@ +import { render, screen } from '@testing-library/react'; + +import { AlertIcon } from '../AlertIcon'; +import styles from '@patternfly/react-styles/css/components/Alert/alert'; + +jest.mock('@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon', () => () => 'Check circle icon mock'); +jest.mock('@patternfly/react-icons/dist/esm/icons/rh-ui-error-fill-icon', () => () => 'Exclamation circle icon mock'); +jest.mock( + '@patternfly/react-icons/dist/esm/icons/rh-ui-warning-fill-icon', + () => () => 'Exclamation triangle icon mock' +); +jest.mock('@patternfly/react-icons/dist/esm/icons/rh-ui-information-fill-icon', () => () => 'Info circle icon mock'); +jest.mock('@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon', () => () => 'Bell icon mock'); + +test('Renders without children', () => { + render( +
    + +
    + ); + + expect(screen.getByTestId('container').firstChild).toBeVisible(); +}); + +test('Renders with the bell icon when variant = custom', () => { + render(); + + expect(screen.getByText('Bell icon mock')).toBeVisible(); +}); + +test('Renders with the check circle icon when variant = success', () => { + render(); + + expect(screen.getByText('Check circle icon mock')).toBeVisible(); +}); + +test('Renders with the exclamation circle icon when variant = danger', () => { + render(); + + expect(screen.getByText('Exclamation circle icon mock')).toBeVisible(); +}); + +test('Renders with the exclamation triangle icon when variant = warning', () => { + render(); + + expect(screen.getByText('Exclamation triangle icon mock')).toBeVisible(); +}); + +test('Renders with the info circle icon when variant = info', () => { + render(); + + expect(screen.getByText('Info circle icon mock')).toBeVisible(); +}); + +test('Renders with custom class names provided via prop', () => { + render(); + + expect(screen.getByText('Bell icon mock')).toHaveClass('test-class'); +}); + +test('Renders with the passed custom icon when one is passed rather than the icon determined by the passed variant', () => { + render(); + + expect(screen.queryByText('Bell icon mock')).not.toBeInTheDocument(); + expect(screen.getByText('Custom icon')).toBeVisible(); +}); + +test(`Renders the icon inside class ${styles.alertIcon}`, () => { + render(); + + expect(screen.getByText('Bell icon mock')).toHaveClass(styles.alertIcon); +}); + +test('Renders with inherited element props spread to the component', () => { + render(); + + expect(screen.getByText('Bell icon mock')).toHaveAccessibleName('Test label'); +}); + +test('Matches snapshot', () => { + const { asFragment } = render(); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Alert/__tests__/AlertToggleExpandButton.test.tsx b/packages/react-core/src/components/Alert/__tests__/AlertToggleExpandButton.test.tsx new file mode 100644 index 00000000000..a37b955f406 --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/AlertToggleExpandButton.test.tsx @@ -0,0 +1,139 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { AlertToggleExpandButton } from '../AlertToggleExpandButton'; +import { AlertContext } from '../AlertContext'; +import styles from '@patternfly/react-styles/css/components/Alert/alert'; + +jest.mock('../../Button'); + +jest.mock('@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon', () => () => 'Icon mock'); + +test('Renders without children', () => { + render( +
    + + + +
    + ); + + expect(screen.getByTestId('container').firstChild).toBeVisible(); +}); + +test('Renders with an aria label composed with the title and variantLabel provided via a context by default', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Toggle variantLabel alert: title'); +}); + +test('Renders with the aria label provided via prop when one is provided', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Aria label prop'); +}); + +test('Does not call the callback provided via onToggleExpand when it is not clicked', () => { + const onToggleExpandMock = jest.fn(); + + render( + + + + ); + + expect(onToggleExpandMock).not.toHaveBeenCalled(); +}); + +test('Calls the callback provided via onToggleExpand when clicked', async () => { + const onToggleExpandMock = jest.fn(); + const user = userEvent.setup(); + + render( + + + + ); + + await user.click(screen.getByRole('button')); + + expect(onToggleExpandMock).toHaveBeenCalledTimes(1); +}); + +test('Does not render the button as aria-expanded by default', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'false'); +}); + +test('Renders the button as aria-expanded when isExpanded = true', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'true'); +}); + +test('Renders with an aria label composed with the title provided via a context and variantLabel provided via prop', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Toggle variantLabelProp alert: title'); +}); + +test('Renders a Button with variant: ButtonVariant.plain', () => { + render( + + + + ); + + expect(screen.getByText('variant: plain')).toBeVisible(); +}); + +test(`Renders with the toggle icon inside class ${styles.alertToggleIcon}`, () => { + render( + + + + ); + + expect(screen.getByText('Icon mock')).toHaveClass(styles.alertToggleIcon); +}); + +test('Renders with inherited element props spread to the component', () => { + render( + + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Matches snapshot', () => { + const { asFragment } = render( + + + + ); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/Alert.test.tsx b/packages/react-core/src/components/Alert/__tests__/Generated/Alert.test.tsx deleted file mode 100644 index 65d864cfb9c..00000000000 --- a/packages/react-core/src/components/Alert/__tests__/Generated/Alert.test.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Alert } from '../../Alert'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Alert should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode
    } - actionClose={undefined} - actionLinks={[]} - children={''} - className={"''"} - aria-label={'string'} - variantLabel={'string'} - isLiveRegion={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionCloseButton.test.tsx b/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionCloseButton.test.tsx index 5c0379a6353..fb3bad4ad4f 100644 --- a/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionCloseButton.test.tsx +++ b/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionCloseButton.test.tsx @@ -1,20 +1,20 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; + import { AlertActionCloseButton } from '../../AlertActionCloseButton'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; +import { AlertContext } from '../../AlertContext'; -it('AlertActionCloseButton should match snapshot (auto-generated)', () => { - const view = shallow( - undefined as any} - aria-label={"''"} - variantLabel={'string'} - /> - ); - expect(view).toMatchSnapshot(); +describe('AlertActionCloseButton', () => { + it('should match snapshot', () => { + const { asFragment } = render( + + console.log('close clicked')} + aria-label="" + variantLabel="" + /> + + ); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionLink.test.tsx b/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionLink.test.tsx index 35ca1fd9f51..e54b8bb1ecd 100644 --- a/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionLink.test.tsx +++ b/packages/react-core/src/components/Alert/__tests__/Generated/AlertActionLink.test.tsx @@ -1,13 +1,12 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { AlertActionLink } from '../../AlertActionLink'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('AlertActionLink should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/AlertGroup.test.tsx b/packages/react-core/src/components/Alert/__tests__/Generated/AlertGroup.test.tsx new file mode 100644 index 00000000000..8f29f8a65fd --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/Generated/AlertGroup.test.tsx @@ -0,0 +1,14 @@ +/** + * This test was generated + */ +import { render } from '@testing-library/react'; +import { AlertGroup } from '../../AlertGroup'; +// any missing imports can usually be resolved by adding them here +import {} from '../..'; + +it('AlertGroup should match snapshot (auto-generated)', () => { + const { asFragment } = render( + ReactNode
    } isToast={true} appendTo={undefined} /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/AlertGroupInline.test.tsx b/packages/react-core/src/components/Alert/__tests__/Generated/AlertGroupInline.test.tsx new file mode 100644 index 00000000000..8301f3bcdaa --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/Generated/AlertGroupInline.test.tsx @@ -0,0 +1,12 @@ +/** + * This test was generated + */ +import { render } from '@testing-library/react'; +import { AlertGroupInline } from '../../AlertGroupInline'; +// any missing imports can usually be resolved by adding them here +import {} from '../..'; + +it('AlertGroupInline should match snapshot (auto-generated)', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/AlertIcon.test.tsx b/packages/react-core/src/components/Alert/__tests__/Generated/AlertIcon.test.tsx index 775220b7d44..06ecd8a01f3 100644 --- a/packages/react-core/src/components/Alert/__tests__/Generated/AlertIcon.test.tsx +++ b/packages/react-core/src/components/Alert/__tests__/Generated/AlertIcon.test.tsx @@ -1,13 +1,12 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { AlertIcon } from '../../AlertIcon'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('AlertIcon should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/Alert.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/Alert.test.tsx.snap deleted file mode 100644 index 6acee74b3f0..00000000000 --- a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/Alert.test.tsx.snap +++ /dev/null @@ -1,32 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Alert should match snapshot (auto-generated) 1`] = ` -
    - -

    - - string - -
    - ReactNode -
    -

    -
    -
    -`; diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionCloseButton.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionCloseButton.test.tsx.snap index f7e3d8cba40..28db37204e9 100644 --- a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionCloseButton.test.tsx.snap +++ b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionCloseButton.test.tsx.snap @@ -1,7 +1,32 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AlertActionCloseButton should match snapshot (auto-generated) 1`] = ` - - - +exports[`AlertActionCloseButton should match snapshot 1`] = ` + + + `; diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionLink.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionLink.test.tsx.snap index 99614afacf5..c615ed2d152 100644 --- a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionLink.test.tsx.snap +++ b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertActionLink.test.tsx.snap @@ -1,11 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AlertActionLink should match snapshot (auto-generated) 1`] = ` - + + + `; diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertGroup.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertGroup.test.tsx.snap new file mode 100644 index 00000000000..c704bee01bc --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertGroup.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AlertGroup should match snapshot (auto-generated) 1`] = ``; diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertGroupInline.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertGroupInline.test.tsx.snap new file mode 100644 index 00000000000..345f8457892 --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertGroupInline.test.tsx.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AlertGroupInline should match snapshot (auto-generated) 1`] = ` + +
      + +`; diff --git a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertIcon.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertIcon.test.tsx.snap index 979cce00275..3467f8aa3d5 100644 --- a/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertIcon.test.tsx.snap +++ b/packages/react-core/src/components/Alert/__tests__/Generated/__snapshots__/AlertIcon.test.tsx.snap @@ -1,13 +1,23 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AlertIcon should match snapshot (auto-generated) 1`] = ` -
      - -
      + +
      + +
      +
      `; diff --git a/packages/react-core/src/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap index f3cf36c2a01..84f6f4b0066 100644 --- a/packages/react-core/src/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap +++ b/packages/react-core/src/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap @@ -1,4936 +1,39 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Alert - danger Action Close Button 1`] = ` - - } - title="Sample danger alert" - variant="danger" -> -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Sample danger alert -

      -
      - - - - - -
      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - danger Action Link 1`] = ` - - test - , - ] - } - title="" - variant="danger" -> -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - danger Action and Title 1`] = ` - - test - , - ] - } - title="Some title" - variant="danger" -> -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - danger Custom aria label 1`] = ` - - test - , - ] - } - aria-label="Custom aria label for danger" - title="Some title" - variant="danger" -> -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - danger Custom icon 1`] = ` - - } - title="custom icon alert title" - variant="danger" -> -
      - - } - variant="danger" - > -
      - - - - - -
      -
      -

      - - Danger alert: - - custom icon alert title -

      -
      - Some noisy alert -
      -
      -
      -`; - -exports[`Alert - danger Description 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - danger Heading level 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - danger Title 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - danger Toast alerts match snapsnot 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Some title -

      -
      - Some toast alert -
      -
      -
      -`; - -exports[`Alert - danger expandable variation 1`] = ` - -
      -
      - - - - - -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Some title -

      -
      -
      -`; - -exports[`Alert - danger inline variation 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Danger alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - default Action Close Button 1`] = ` - - } - title="Sample default alert" - variant="default" -> -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Sample default alert -

      -
      - - - - - -
      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - default Action Link 1`] = ` - - test - , - ] - } - title="" - variant="default" -> -
      - -
      - - - - - -
      -
      -

      - - Default alert: - -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - default Action and Title 1`] = ` - - test - , - ] - } - title="Some title" - variant="default" -> -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - default Custom aria label 1`] = ` - - test - , - ] - } - aria-label="Custom aria label for default" - title="Some title" - variant="default" -> -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - default Custom icon 1`] = ` - - } - title="custom icon alert title" - variant="default" -> -
      - - } - variant="default" - > -
      - - - - - -
      -
      -

      - - Default alert: - - custom icon alert title -

      -
      - Some noisy alert -
      -
      -
      -`; - -exports[`Alert - default Description 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Default alert: - -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - default Heading level 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - default Title 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - default Toast alerts match snapsnot 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Some title -

      -
      - Some toast alert -
      -
      -
      -`; - -exports[`Alert - default expandable variation 1`] = ` - -
      -
      - - - - - -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Some title -

      -
      -
      -`; - -exports[`Alert - default inline variation 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Default alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - info Action Close Button 1`] = ` - - } - title="Sample info alert" - variant="info" -> -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Sample info alert -

      -
      - - - - - -
      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - info Action Link 1`] = ` - - test - , - ] - } - title="" - variant="info" -> -
      - -
      - - - - - -
      -
      -

      - - Info alert: - -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - info Action and Title 1`] = ` - - test - , - ] - } - title="Some title" - variant="info" -> -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - info Custom aria label 1`] = ` - - test - , - ] - } - aria-label="Custom aria label for info" - title="Some title" - variant="info" -> -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - info Custom icon 1`] = ` - - } - title="custom icon alert title" - variant="info" -> -
      - - } - variant="info" - > -
      - - - - - -
      -
      -

      - - Info alert: - - custom icon alert title -

      -
      - Some noisy alert -
      -
      -
      -`; - -exports[`Alert - info Description 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Info alert: - -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - info Heading level 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - info Title 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - info Toast alerts match snapsnot 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Some title -

      -
      - Some toast alert -
      -
      -
      -`; - -exports[`Alert - info expandable variation 1`] = ` - -
      -
      - - - - - -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Some title -

      -
      -
      -`; - -exports[`Alert - info inline variation 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Info alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - success Action Close Button 1`] = ` - - } - title="Sample success alert" - variant="success" -> -
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Sample success alert -

      -
      - - - - - -
      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - success Action Link 1`] = ` - - test - , - ] - } - title="" - variant="success" -> -
      - -
      - - - - - -
      -
      -

      - - Success alert: - -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - success Action and Title 1`] = ` - - test - , - ] - } - title="Some title" - variant="success" -> -
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - success Custom aria label 1`] = ` - - test - , - ] - } - aria-label="Custom aria label for success" - title="Some title" - variant="success" -> -
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - success Custom icon 1`] = ` - - } - title="custom icon alert title" - variant="success" -> -
      - - } - variant="success" - > -
      - - - - - -
      -
      -

      - - Success alert: - - custom icon alert title -

      -
      - Some noisy alert -
      -
      -
      -`; - -exports[`Alert - success Description 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Success alert: - -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - success Heading level 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - success Title 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - success Toast alerts match snapsnot 1`] = ` - +exports[`Matches snapshot 1`] = ` +
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Some title -

      -
      - Some toast alert -
      -
      -
      -`; - -exports[`Alert - success expandable variation 1`] = ` - -
      -
      - - - - - -
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Some title -

      -
      -
      -`; - -exports[`Alert - success inline variation 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Success alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - warning Action Close Button 1`] = ` - - } - title="Sample warning alert" - variant="warning" -> -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - - Sample warning alert -

      -
      - - - - - -
      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - warning Action Link 1`] = ` - - test - , - ] - } - title="" - variant="warning" -> -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - warning Action and Title 1`] = ` - - test - , - ] - } - title="Some title" - variant="warning" -> -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - warning Custom aria label 1`] = ` - - test - , - ] - } - aria-label="Custom aria label for warning" - title="Some title" - variant="warning" -> -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - - Some title -

      -
      - Some alert -
      -
      - - - - - -
      -
      -
      -`; - -exports[`Alert - warning Custom icon 1`] = ` - - } - title="custom icon alert title" - variant="warning" -> -
      - - } - variant="warning" - > -
      - - - - - -
      -
      -

      - - Warning alert: - - custom icon alert title -

      -
      - Some noisy alert -
      -
      -
      -`; - -exports[`Alert - warning Description 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - warning Heading level 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - - Some title -

      -
      - Some alert -
      -
      -
      -`; - -exports[`Alert - warning Title 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - - Some title -

      -
      - Some alert +
      +

      + custom icon: +

      +

      + variant: custom +

      -
      - -`; - -exports[`Alert - warning Toast alerts match snapsnot 1`] = ` - -
      - -
      - - - - - -
      -

      - Warning alert: + Custom alert: Some title

      Some toast alert
      -
      -`; - -exports[`Alert - warning expandable variation 1`] = ` - -
      -
      - - - - - -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - - Some title -

      -
      -
      -`; - -exports[`Alert - warning inline variation 1`] = ` - -
      - -
      - - - - - -
      -
      -

      - - Warning alert: - - Some title -

      -
      - Some alert -
      -
      -
      + `; diff --git a/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertActionCloseButton.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertActionCloseButton.test.tsx.snap new file mode 100644 index 00000000000..c59f313bb6b --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertActionCloseButton.test.tsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + + +

      + variant: link +

      +

      + Test label +

      +

      + isInline: true +

      +

      + iconPosition: undefined +

      +
      + +`; diff --git a/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertIcon.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertIcon.test.tsx.snap new file mode 100644 index 00000000000..ac4c1b39d3d --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertIcon.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches snapshot 1`] = ` + +
      + Bell icon mock +
      +
      +`; diff --git a/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertToggleExpandButton.test.tsx.snap b/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertToggleExpandButton.test.tsx.snap new file mode 100644 index 00000000000..9e7ec7f0604 --- /dev/null +++ b/packages/react-core/src/components/Alert/__tests__/__snapshots__/AlertToggleExpandButton.test.tsx.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches snapshot 1`] = ` + + - - - {alerts} - - - ); -}; +## Alert group examples + +An alert group stacks and positions 2 or more alerts in a live region, either in a layer over the main content of a page or inline with the page content. Alert groups should always rank alerts by age, stacking new alerts on top of old ones as they surface. + +### Alert group variants + +Alert groups can be one of the following variants: + +| Variant | Description | +| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Static inline | Static inline alert groups contain alerts that appear when the page loads, and are seen within the normal page content flow. These groups should not contain alerts that will dynamically appear or update. | +| Toast | Toast alert groups contain alerts that typically appear in response to an asynchronous event or user action. These groups are positioned on top of other content at the top right of the page. | +| Dynamic | Dynamic alert groups contain alerts that typically appear in response to a user action, and are seen within the normal page content flow. | + +Dynamic alerts that are generated after the page initially loads must be appended to either a toast or dynamic `AlertGroup`, both of which must use the `isLiveRegion` property. New alerts appended to a toast or dynamic group will be announced by assistive technologies the moment the change happens. For information about customizing this announcement, read the [aria-atomic and aria-relevant](/components/alert/accessibility#aria-atomic-and-aria-relevant) section of the alert accessibility documentation. + +### Static inline alert group + +All alert group variants may combine multiple [alert variants](/components/alert) For example, the following static inline alert group includes one "success" alert and one "info" alert. + +```ts file="AlertGroupStatic.tsx" + ``` -### Truncate -```ts -import React from 'react'; -import { Alert } from '@patternfly/react-core'; - - - - - - +### Toast alert group + +Toast alert groups are created by passing in the `isToast` and `isLiveRegion` properties. + +Click the buttons in the example below to add alerts to a toast group. + +```ts file="AlertGroupToast.tsx" + ``` -### Custom icons -```ts -import React from 'react'; -import { Alert } from '@patternfly/react-core'; -import UsersIcon from '@patternfly/react-icons/dist/esm/icons/users-icon'; -import BoxIcon from '@patternfly/react-icons/dist/esm/icons/box-icon'; -import DatabaseIcon from '@patternfly/react-icons/dist/esm/icons/database-icon'; -import ServerIcon from '@patternfly/react-icons/dist/esm/icons/server-icon'; -import LaptopIcon from '@patternfly/react-icons/dist/esm/icons/laptop-icon'; +### Toast alert group with overflow capture + +Users will see an overflow message once a predefined number of alerts are displayed. They will not see any alerts beyond the display limit, which must be explicitly set. + +In the following example, an overflow message will appear when more than 4 alerts would be shown. When a 5th alert would appear, an overflow message is shown instead. + +When an overflow message appears in an `AlertGroup` using the `isLiveRegion` property, the "view 1 more alert" text label will be announced, but the alert message will not. + +Users navigating via keyboard or another assistive technology will need a way to navigate to and reveal hidden alerts before they disappear. Alternatively, there should be a place where notifications or alerts are collected to be viewed or read later. + +```ts file="AlertGroupToastOverflowCapture.tsx" + +``` + +### Asynchronous alert groups + +The following example shows how alerts can be triggered by an asynchronous event in the application. You can customize how an alert will be announced to assistive technology by adjusting the value of the `aria-live` property. Click the "start async" alert button below and then click the buttons in the above toast examples to demonstrate how asynchronous events add alerts to a group. Click the "stop async alerts" button to halt this behavior. + +See the [alert accessibility tab](/components/alert/accessibility) for more information on customizing this behavior. + +```ts file="AlertGroupAsync.tsx" + +``` + +### Dynamic alert groups + +Click the buttons in the example below to add dynamic alerts to a group. + +```ts file="AlertGroupSingularDynamic.tsx" + +``` + +### Dynamic alert group with overflow message + +In the following example, there can be a maximum of 4 alerts shown at once. + +```ts file="AlertGroupSingularDynamicOverflow.tsx" + +``` + +### Multiple dynamic alert groups + +You may add multiple alerts to an alert group at once. Click the "add alert collection" button in the example below to add a batch of 3 toast alerts to a group. + +```ts file="AlertGroupMultipleDynamic.tsx" - - } title="Default alert title" /> - } variant="info" title="Info alert title" /> - } variant="success" title="Success alert title" /> - } variant="warning" title="Warning alert title" /> - } variant="danger" title="Danger alert title" /> - ``` diff --git a/packages/react-core/src/components/Alert/examples/AlertAsyncLiveRegion.tsx b/packages/react-core/src/components/Alert/examples/AlertAsyncLiveRegion.tsx index 39517dc90f6..51553032071 100644 --- a/packages/react-core/src/components/Alert/examples/AlertAsyncLiveRegion.tsx +++ b/packages/react-core/src/components/Alert/examples/AlertAsyncLiveRegion.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { Fragment, useEffect, useState } from 'react'; import { Alert, AlertGroup, AlertVariant, ToggleGroup, ToggleGroupItem } from '@patternfly/react-core'; interface AlertInfo { @@ -8,15 +8,15 @@ interface AlertInfo { } export const AsyncLiveRegionAlert: React.FunctionComponent = () => { - const [alerts, setAlerts] = React.useState([]); - const [isActive, setIsActive] = React.useState(false); + const [alerts, setAlerts] = useState([]); + const [isActive, setIsActive] = useState(false); const getUniqueId: () => number = () => new Date().getTime(); const addAlert = (alertInfo: AlertInfo) => { - setAlerts(prevAlertInfo => [...prevAlertInfo, alertInfo]); + setAlerts((prevAlertInfo) => [alertInfo, ...prevAlertInfo]); }; - React.useEffect(() => { + useEffect(() => { let timer = null; if (isActive) { timer = setInterval(() => { @@ -36,26 +36,20 @@ export const AsyncLiveRegionAlert: React.FunctionComponent = () => { }, [isActive, alerts]); return ( - + setIsActive(true)} - /> - setIsActive(false)} + onChange={() => setIsActive(!isActive)} /> - + {alerts.map(({ title, variant, key }) => ( ))} - + ); }; diff --git a/packages/react-core/src/components/Alert/examples/AlertCustomIcons.tsx b/packages/react-core/src/components/Alert/examples/AlertCustomIcons.tsx new file mode 100644 index 00000000000..ba9116d64f0 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertCustomIcons.tsx @@ -0,0 +1,17 @@ +import { Fragment } from 'react'; +import { Alert } from '@patternfly/react-core'; +import UsersIcon from '@patternfly/react-icons/dist/esm/icons/users-icon'; +import BoxIcon from '@patternfly/react-icons/dist/esm/icons/box-icon'; +import DatabaseIcon from '@patternfly/react-icons/dist/esm/icons/database-icon'; +import ServerIcon from '@patternfly/react-icons/dist/esm/icons/server-icon'; +import LaptopIcon from '@patternfly/react-icons/dist/esm/icons/laptop-icon'; + +export const AlertCustomIcons: React.FunctionComponent = () => ( + + } title="Default alert title" /> + } variant="info" title="Info alert title" /> + } variant="success" title="Success alert title" /> + } variant="warning" title="Warning alert title" /> + } variant="danger" title="Danger alert title" /> + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertDynamicLiveRegion.tsx b/packages/react-core/src/components/Alert/examples/AlertDynamicLiveRegion.tsx index dd2c00c92f0..6698cc374c8 100644 --- a/packages/react-core/src/components/Alert/examples/AlertDynamicLiveRegion.tsx +++ b/packages/react-core/src/components/Alert/examples/AlertDynamicLiveRegion.tsx @@ -1,5 +1,6 @@ -import React from 'react'; -import { Alert, AlertGroup, AlertVariant, InputGroup } from '@patternfly/react-core'; +import { Fragment, useState } from 'react'; +import { Alert, AlertGroup, AlertVariant, Flex, FlexItem } from '@patternfly/react-core'; +import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; interface AlertInfo { title: string; @@ -8,12 +9,12 @@ interface AlertInfo { } export const DynamicLiveRegionAlert: React.FunctionComponent = () => { - const [alerts, setAlerts] = React.useState([]); + const [alerts, setAlerts] = useState([]); const getUniqueId: () => number = () => new Date().getTime(); - const btnClasses = ['pf-c-button', 'pf-m-secondary'].join(' '); + const btnClasses = [buttonStyles.button, buttonStyles.modifiers.secondary].join(' '); const addAlert = (alertInfo: AlertInfo) => { - setAlerts(prevAlertInfo => [...prevAlertInfo, alertInfo]); + setAlerts((prevAlertInfo) => [alertInfo, ...prevAlertInfo]); }; const addSuccessAlert = () => { @@ -39,23 +40,29 @@ export const DynamicLiveRegionAlert: React.FunctionComponent = () => { }; return ( - - - - - - - + + + + + + + + + + + + + {alerts.map(({ title, variant, key }) => ( ))} - + ); }; diff --git a/packages/react-core/src/components/Alert/examples/AlertExpandable.tsx b/packages/react-core/src/components/Alert/examples/AlertExpandable.tsx new file mode 100644 index 00000000000..9fe9ab5b53d --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertExpandable.tsx @@ -0,0 +1,36 @@ +import { Fragment } from 'react'; +import { Alert, AlertActionCloseButton, AlertActionLink } from '@patternfly/react-core'; + +export const AlertExpandable: React.FunctionComponent = () => ( + + console.log('Clicked the close button')} />} + > +

      Success alert description. This should tell the user more information about the alert.

      +
      + + + View details + + console.log('Clicked on Ignore')} + > + Ignore + +
      + } + > +

      Success alert description. This should tell the user more information about the alert.

      + + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertGroupAsync.tsx b/packages/react-core/src/components/Alert/examples/AlertGroupAsync.tsx new file mode 100644 index 00000000000..4bcb2a8c7e4 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertGroupAsync.tsx @@ -0,0 +1,79 @@ +import { Fragment, useState } from 'react'; +import { + Alert, + AlertProps, + AlertGroup, + AlertActionCloseButton, + AlertVariant, + InputGroup, + InputGroupItem, + useInterval +} from '@patternfly/react-core'; +import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; + +export const AlertGroupAsync: React.FunctionComponent = () => { + const [alerts, setAlerts] = useState[]>([]); + const [isRunning, setIsRunning] = useState(false); + + const btnClasses = [buttonStyles.button, buttonStyles.modifiers.secondary].join(' '); + + const getUniqueId = () => new Date().getTime(); + + const addAlert = () => { + setAlerts((prevAlerts) => [ + { + title: `Async notification ${prevAlerts.length + 1} was added to the queue.`, + variant: 'danger', + key: getUniqueId() + }, + ...prevAlerts + ]); + }; + + const removeAlert = (key: React.Key) => { + setAlerts((prevAlerts) => [...prevAlerts.filter((alert) => alert.key !== key)]); + }; + + const startAsyncAlerts = () => { + setIsRunning(true); + }; + + const stopAsyncAlerts = () => { + setIsRunning(false); + }; + + useInterval(addAlert, isRunning ? 4500 : null); + + return ( + + + + + + + + + + + {alerts.map(({ title, variant, key }) => ( + removeAlert(key)} + /> + } + /> + ))} + + + ); +}; diff --git a/packages/react-core/src/components/Alert/examples/AlertGroupMultipleDynamic.tsx b/packages/react-core/src/components/Alert/examples/AlertGroupMultipleDynamic.tsx new file mode 100644 index 00000000000..311c1f75b7d --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertGroupMultipleDynamic.tsx @@ -0,0 +1,63 @@ +import { Fragment, useState } from 'react'; +import { + Alert, + AlertProps, + AlertGroup, + AlertActionCloseButton, + AlertVariant, + Flex, + FlexItem +} from '@patternfly/react-core'; +import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; + +export const AlertGroupMultipleDynamic: React.FunctionComponent = () => { + const [alerts, setAlerts] = useState[]>([]); + + const addAlerts = (incomingAlerts: Partial[]) => { + setAlerts((prevAlerts) => [...incomingAlerts, ...prevAlerts]); + }; + + const removeAlert = (key: React.Key) => { + setAlerts((prevAlerts) => [...prevAlerts.filter((alert) => alert.key !== key)]); + }; + + const btnClasses = [buttonStyles.button, buttonStyles.modifiers.secondary].join(' '); + + const getUniqueId = () => String.fromCharCode(65 + Math.floor(Math.random() * 26)) + Date.now(); + + const addAlertCollection = () => { + addAlerts([ + { title: 'First alert notification.', variant: 'success', key: getUniqueId() }, + { title: 'Second alert notification.', variant: 'warning', key: getUniqueId() }, + { title: 'Third alert notification.', variant: 'danger', key: getUniqueId() } + ]); + }; + + return ( + + + + + + + + {alerts.map(({ title, variant, key }) => ( + removeAlert(key)} + /> + } + /> + ))} + + + ); +}; diff --git a/packages/react-core/src/components/Alert/examples/AlertGroupSingularDynamic.tsx b/packages/react-core/src/components/Alert/examples/AlertGroupSingularDynamic.tsx new file mode 100644 index 00000000000..b4087fb7017 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertGroupSingularDynamic.tsx @@ -0,0 +1,78 @@ +import { Fragment, useState } from 'react'; +import { + Alert, + AlertProps, + AlertGroup, + AlertActionCloseButton, + AlertVariant, + Flex, + FlexItem +} from '@patternfly/react-core'; +import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; + +export const AlertGroupSingularDynamic: React.FunctionComponent = () => { + const [alerts, setAlerts] = useState[]>([]); + + const addAlert = (title: string, variant: AlertProps['variant'], key: React.Key) => { + setAlerts((prevAlerts) => [{ title, variant, key }, ...prevAlerts]); + }; + + const removeAlert = (key: React.Key) => { + setAlerts((prevAlerts) => [...prevAlerts.filter((alert) => alert.key !== key)]); + }; + + const btnClasses = [buttonStyles.button, buttonStyles.modifiers.secondary].join(' '); + + const getUniqueId = () => new Date().getTime(); + + const addSuccessAlert = () => { + addAlert('Success alert', 'success', getUniqueId()); + }; + + const addDangerAlert = () => { + addAlert('Danger alert', 'danger', getUniqueId()); + }; + + const addInfoAlert = () => { + addAlert('Info alert', 'info', getUniqueId()); + }; + + return ( + + + + + + + + + + + + + + {alerts.map(({ title, variant, key }) => ( + removeAlert(key)} + /> + } + /> + ))} + + + ); +}; diff --git a/packages/react-core/src/components/Alert/examples/AlertGroupSingularDynamicOverflow.tsx b/packages/react-core/src/components/Alert/examples/AlertGroupSingularDynamicOverflow.tsx new file mode 100644 index 00000000000..fa1a140c041 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertGroupSingularDynamicOverflow.tsx @@ -0,0 +1,97 @@ +import { Fragment, useState } from 'react'; +import { + Alert, + AlertProps, + AlertGroup, + AlertActionCloseButton, + AlertVariant, + Flex, + FlexItem +} from '@patternfly/react-core'; +import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; + +export const AlertGroupSingularDynamicOverflow: React.FunctionComponent = () => { + const [alerts, setAlerts] = useState[]>([]); + const [overflowMessage, setOverflowMessage] = useState(''); + + const maxDisplayed = 4; + + const getOverflowMessage = (alertsNumber: number) => { + const overflow = alertsNumber - maxDisplayed; + if (overflow > 0) { + return `View ${overflow} more alerts`; + } + return ''; + }; + + const addAlert = (title: string, variant: AlertProps['variant'], key: React.Key) => { + setAlerts((prevAlerts) => [{ title, variant, key }, ...prevAlerts]); + setOverflowMessage(getOverflowMessage(alerts.length + 1)); + }; + + const removeAlert = (key: React.Key) => { + const newAlerts = alerts.filter((alert) => alert.key !== key); + setAlerts(newAlerts); + setOverflowMessage(getOverflowMessage(newAlerts.length)); + }; + + const btnClasses = [buttonStyles.button, buttonStyles.modifiers.secondary].join(' '); + + const getUniqueId = () => new Date().getTime(); + + const addSuccessAlert = () => { + addAlert('Success alert', 'success', getUniqueId()); + }; + + const addDangerAlert = () => { + addAlert('Danger alert', 'danger', getUniqueId()); + }; + + const addInfoAlert = () => { + addAlert('Info alert', 'info', getUniqueId()); + }; + + const onOverflowClick = () => { + // eslint-disable-next-line no-console + console.log('Overflow message clicked'); + }; + + return ( + + + + + + + + + + + + + + {alerts.slice(0, maxDisplayed).map(({ key, variant, title }) => ( + removeAlert(key)} + /> + } + key={key} + /> + ))} + + + ); +}; diff --git a/packages/react-core/src/components/Alert/examples/AlertGroupStatic.tsx b/packages/react-core/src/components/Alert/examples/AlertGroupStatic.tsx new file mode 100644 index 00000000000..1477cefc811 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertGroupStatic.tsx @@ -0,0 +1,11 @@ +import { Fragment } from 'react'; +import { Alert, AlertGroup } from '@patternfly/react-core'; + +export const AlertGroupStatic: React.FunctionComponent = () => ( + + + + + + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertGroupToast.tsx b/packages/react-core/src/components/Alert/examples/AlertGroupToast.tsx new file mode 100644 index 00000000000..460eb9ddb6a --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertGroupToast.tsx @@ -0,0 +1,77 @@ +import { Fragment, useState } from 'react'; +import { + Alert, + AlertProps, + AlertGroup, + AlertActionCloseButton, + AlertVariant, + Flex, + FlexItem +} from '@patternfly/react-core'; +import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; + +export const AlertGroupToast: React.FunctionComponent = () => { + const [alerts, setAlerts] = useState[]>([]); + + const addAlert = (title: string, variant: AlertProps['variant'], key: React.Key) => { + setAlerts((prevAlerts) => [{ title, variant, key }, ...prevAlerts]); + }; + + const removeAlert = (key: React.Key) => { + setAlerts((prevAlerts) => [...prevAlerts.filter((alert) => alert.key !== key)]); + }; + + const btnClasses = [buttonStyles.button, buttonStyles.modifiers.secondary].join(' '); + + const getUniqueId = () => new Date().getTime(); + + const addSuccessAlert = () => { + addAlert('Toast success alert', 'success', getUniqueId()); + }; + + const addDangerAlert = () => { + addAlert('Toast danger alert', 'danger', getUniqueId()); + }; + + const addInfoAlert = () => { + addAlert('Toast info alert', 'info', getUniqueId()); + }; + + return ( + + + + + + + + + + + + + + {alerts.map(({ key, variant, title }) => ( + removeAlert(key)} + /> + } + key={key} + /> + ))} + + + ); +}; diff --git a/packages/react-core/src/components/Alert/examples/AlertGroupToastOverflowCapture.tsx b/packages/react-core/src/components/Alert/examples/AlertGroupToastOverflowCapture.tsx new file mode 100644 index 00000000000..d4f567551dc --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertGroupToastOverflowCapture.tsx @@ -0,0 +1,102 @@ +import { Fragment, useState } from 'react'; +import { + Alert, + AlertProps, + AlertGroup, + AlertActionCloseButton, + AlertVariant, + Flex, + FlexItem +} from '@patternfly/react-core'; +import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; + +export const AlertGroupToastOverflowCapture: React.FunctionComponent = () => { + const [alerts, setAlerts] = useState[]>([]); + const [overflowMessage, setOverflowMessage] = useState(''); + + const maxDisplayed = 4; + + const getOverflowMessage = (alertsNumber: number) => { + const overflow = alertsNumber - maxDisplayed; + if (overflow > 0) { + return `View ${overflow} more alerts`; + } + return ''; + }; + + const addAlert = (title: string, variant: AlertProps['variant'], key: React.Key) => { + setAlerts((prevAlerts) => [{ title, variant, key }, ...prevAlerts]); + setOverflowMessage(getOverflowMessage(alerts.length + 1)); + }; + + const removeAlert = (key: React.Key) => { + const newAlerts = alerts.filter((alert) => alert.key !== key); + setAlerts(newAlerts); + setOverflowMessage(getOverflowMessage(newAlerts.length)); + }; + + const btnClasses = [buttonStyles.button, buttonStyles.modifiers.secondary].join(' '); + + const getUniqueId = () => new Date().getTime(); + + const addSuccessAlert = () => { + addAlert('Toast success alert', 'success', getUniqueId()); + }; + + const addDangerAlert = () => { + addAlert('Toast danger alert', 'danger', getUniqueId()); + }; + + const addInfoAlert = () => { + addAlert('Toast info alert', 'info', getUniqueId()); + }; + + const onOverflowClick = () => { + // eslint-disable-next-line no-console + console.log('Overflow message clicked'); + }; + + return ( + + + + + + + + + + + + + + {alerts.slice(0, maxDisplayed).map(({ key, variant, title }) => ( + removeAlert(key)} + /> + } + key={key} + /> + ))} + + + ); +}; diff --git a/packages/react-core/src/components/Alert/examples/AlertInlineVariants.tsx b/packages/react-core/src/components/Alert/examples/AlertInlineVariants.tsx new file mode 100644 index 00000000000..011401c76da --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertInlineVariants.tsx @@ -0,0 +1,12 @@ +import { Fragment } from 'react'; +import { Alert } from '@patternfly/react-core'; + +export const AlertInlineVariants: React.FunctionComponent = () => ( + + + + + + + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertInlineVariations.tsx b/packages/react-core/src/components/Alert/examples/AlertInlineVariations.tsx new file mode 100644 index 00000000000..9e3029a4646 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertInlineVariations.tsx @@ -0,0 +1,45 @@ +import { Fragment } from 'react'; +import { Alert, AlertActionCloseButton, AlertActionLink } from '@patternfly/react-core'; + +export const AlertInlineVariations: React.FunctionComponent = () => ( + + + + View details + + console.log('Clicked on Ignore')} + > + Ignore + + + } + > +

      Success alert description. This should tell the user more information about the alert.

      + + +

      + Success alert description. This should tell the user more information about the alert.{' '} + This is a link. +

      +
      + console.log('Clicked the close button')} />} + > +

      Short alert description.

      +
      + + +

      Short alert description.

      +
      + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertPlainInlineVariants.tsx b/packages/react-core/src/components/Alert/examples/AlertPlainInlineVariants.tsx new file mode 100644 index 00000000000..2c63b045482 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertPlainInlineVariants.tsx @@ -0,0 +1,12 @@ +import { Fragment } from 'react'; +import { Alert } from '@patternfly/react-core'; + +export const AlertPlainInlineVariants: React.FunctionComponent = () => ( + + + + + + + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertPlainInlineVariations.tsx b/packages/react-core/src/components/Alert/examples/AlertPlainInlineVariations.tsx new file mode 100644 index 00000000000..0a1cbb368aa --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertPlainInlineVariations.tsx @@ -0,0 +1,7 @@ +import { Alert } from '@patternfly/react-core'; + +export const AlertPlainInlineVariations: React.FunctionComponent = () => ( + +

      Success alert description. This should tell the user more information about the alert.

      +
      +); diff --git a/packages/react-core/src/components/Alert/examples/AlertStaticLiveRegion.tsx b/packages/react-core/src/components/Alert/examples/AlertStaticLiveRegion.tsx new file mode 100644 index 00000000000..b5f3bf17724 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertStaticLiveRegion.tsx @@ -0,0 +1,29 @@ +import { Fragment } from 'react'; +import { Alert, AlertActionCloseButton } from '@patternfly/react-core'; + +export const AlertStaticLiveRegion: React.FunctionComponent = () => ( + + console.log('Clicked the close button')} />} + > + This alert uses the recommended isLiveRegion prop to automatically set ARIA attributes and CSS + classes. + + console.log('Clicked the close button')} />} + > + You can alternatively omit the isLiveRegion prop to specify ARIA attributes and CSS manually on the + containing element. + + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertTimeout.tsx b/packages/react-core/src/components/Alert/examples/AlertTimeout.tsx new file mode 100644 index 00000000000..57eb3a8ccd4 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertTimeout.tsx @@ -0,0 +1,45 @@ +import { Fragment, useState } from 'react'; +import { Alert, AlertActionLink, AlertGroup, Button } from '@patternfly/react-core'; + +export const AlertTimeout: React.FunctionComponent = () => { + const [alerts, setAlerts] = useState([]); + const [newAlertKey, setNewAlertKey] = useState(0); + + const onClick = () => { + const timeout = 8000; + setNewAlertKey((key) => key + 1); + setAlerts((prevAlerts) => [ + + + View details + + console.log('Clicked on Ignore')} + > + Ignore + + + } + key={newAlertKey} + > + This alert will dismiss after {`${timeout / 1000} seconds`} + , + ...prevAlerts + ]); + }; + + return ( + + + + {alerts} + + + ); +}; diff --git a/packages/react-core/src/components/Alert/examples/AlertTruncated.tsx b/packages/react-core/src/components/Alert/examples/AlertTruncated.tsx new file mode 100644 index 00000000000..57e903b13d5 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertTruncated.tsx @@ -0,0 +1,28 @@ +import { Fragment } from 'react'; +import { Alert } from '@patternfly/react-core'; + +export const AlertTruncated: React.FunctionComponent = () => ( + + + + + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertVariants.tsx b/packages/react-core/src/components/Alert/examples/AlertVariants.tsx new file mode 100644 index 00000000000..575b6cee161 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertVariants.tsx @@ -0,0 +1,12 @@ +import { Fragment } from 'react'; +import { Alert } from '@patternfly/react-core'; + +export const AlertVariants: React.FunctionComponent = () => ( + + + + + + + +); diff --git a/packages/react-core/src/components/Alert/examples/AlertVariations.tsx b/packages/react-core/src/components/Alert/examples/AlertVariations.tsx new file mode 100644 index 00000000000..da6241b4352 --- /dev/null +++ b/packages/react-core/src/components/Alert/examples/AlertVariations.tsx @@ -0,0 +1,43 @@ +import { Fragment } from 'react'; +import { Alert, AlertActionCloseButton, AlertActionLink } from '@patternfly/react-core'; + +export const AlertVariations: React.FunctionComponent = () => ( + + + + View details + + console.log('Clicked on Ignore')} + > + Ignore + + + } + > +

      Success alert description. This should tell the user more information about the alert.

      +
      + +

      + Success alert description. This should tell the user more information about the alert.{' '} + This is a link. +

      +
      + console.log('Clicked the close button')} />} + > +

      Short alert description.

      +
      + + +

      Short alert description.

      +
      + +); diff --git a/packages/react-core/src/components/Alert/examples/alert.css b/packages/react-core/src/components/Alert/examples/alert.css index 763996658f3..ae21dac27b3 100644 --- a/packages/react-core/src/components/Alert/examples/alert.css +++ b/packages/react-core/src/components/Alert/examples/alert.css @@ -1,3 +1,3 @@ -.ws-react-c-alert .pf-c-alert { +.ws-react-c-alert .pf-v6-c-alert { margin-bottom: 21px; } diff --git a/packages/react-core/src/components/Alert/index.ts b/packages/react-core/src/components/Alert/index.ts index 0c84bd74c44..d5b940cc0a1 100644 --- a/packages/react-core/src/components/Alert/index.ts +++ b/packages/react-core/src/components/Alert/index.ts @@ -2,3 +2,4 @@ export * from './Alert'; export * from './AlertContext'; export * from './AlertActionCloseButton'; export * from './AlertActionLink'; +export * from './AlertGroup'; diff --git a/packages/react-core/src/components/AlertGroup/AlertGroup.tsx b/packages/react-core/src/components/AlertGroup/AlertGroup.tsx deleted file mode 100644 index 2a8c6e89b1a..00000000000 --- a/packages/react-core/src/components/AlertGroup/AlertGroup.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import { canUseDOM } from '../../helpers'; -import { AlertGroupInline } from './AlertGroupInline'; - -export interface AlertGroupProps extends Omit, 'className'> { - /** Additional classes added to the AlertGroup */ - className?: string; - /** Alerts to be rendered in the AlertGroup */ - children?: React.ReactNode; - /** Toast notifications are positioned at the top right corner of the viewport */ - isToast?: boolean; - /** Turns the container into a live region so that changes to content within the AlertGroup, such as appending an Alert, are reliably announced to assistive technology. */ - isLiveRegion?: boolean; - /** Determine where the alert is appended to */ - appendTo?: HTMLElement | (() => HTMLElement); -} - -interface AlertGroupState { - container: HTMLElement; -} - -export class AlertGroup extends React.Component { - static displayName = 'AlertGroup'; - state = { - container: undefined - } as AlertGroupState; - - componentDidMount() { - const container = document.createElement('div'); - const target: HTMLElement = this.getTargetElement(); - this.setState({ container }); - target.appendChild(container); - } - - componentWillUnmount() { - const target: HTMLElement = this.getTargetElement(); - if (this.state.container) { - target.removeChild(this.state.container); - } - } - - getTargetElement() { - const appendTo = this.props.appendTo; - if (typeof appendTo === 'function') { - return appendTo(); - } - return appendTo || document.body; - } - - render() { - const { className, children, isToast, isLiveRegion, ...props } = this.props; - const alertGroup = ( - - {children} - - ); - if (!this.props.isToast) { - return alertGroup; - } - - const container = this.state.container; - - if (!canUseDOM || !container) { - return null; - } - - return ReactDOM.createPortal(alertGroup, container); - } -} diff --git a/packages/react-core/src/components/AlertGroup/AlertGroupInline.tsx b/packages/react-core/src/components/AlertGroup/AlertGroupInline.tsx deleted file mode 100644 index 8024a95bb64..00000000000 --- a/packages/react-core/src/components/AlertGroup/AlertGroupInline.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/AlertGroup/alert-group'; -import { AlertGroupProps } from './AlertGroup'; - -export const AlertGroupInline: React.FunctionComponent = ({ - className, - children, - isToast, - isLiveRegion, - ...rest -}: AlertGroupProps) => ( -
        - {React.Children.toArray(children).map((Alert: React.ReactNode, index: number) => ( -
      • {Alert}
      • - ))} -
      -); -AlertGroupInline.displayName = 'AlertGroupInline'; diff --git a/packages/react-core/src/components/AlertGroup/__tests__/AlertGroup.test.tsx b/packages/react-core/src/components/AlertGroup/__tests__/AlertGroup.test.tsx deleted file mode 100644 index 78b3b480a42..00000000000 --- a/packages/react-core/src/components/AlertGroup/__tests__/AlertGroup.test.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import * as React from 'react'; -import { shallow, mount } from 'enzyme'; -import { Alert } from '../../Alert'; -import { AlertGroup } from '../../AlertGroup'; -import { AlertActionCloseButton } from '../../../components/Alert/AlertActionCloseButton'; - -jest.spyOn(document, 'createElement'); -jest.spyOn(document.body, 'addEventListener'); - -test('Alert Group works with zero children', () => { - const view = shallow(); - expect(view).toBeTruthy(); -}); - -test('Alert Group should match snapshot', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('Alert Group works with n children', () => { - const view = shallow( - - - - - ); - expect(view).toBeTruthy(); -}); - -test('Standard Alert Group is not a toast alert group', () => { - const wrapper = mount( - - - - ); - expect(wrapper.find('.pf-c-alert-group.pf-m-toast')).toHaveLength(0); - expect(wrapper).toMatchSnapshot(); -}); - -test('Toast Alert Group contains expected modifier class', () => { - const wrapper = mount( - - - - ); - expect(wrapper.find('.pf-c-alert-group.pf-m-toast')).toHaveLength(1); - expect(wrapper).toMatchSnapshot(); -}); - -test('Alert Group creates a container element once for div', () => { - const view = shallow( Test About Modal ); - view.update(); - expect(document.createElement).toBeCalledWith('div'); - expect(document.createElement).toHaveBeenCalledTimes(1); -}); - -test('alertgroup closes when alerts are closed', () => { - const onClose = jest.fn(); - const wrapper = mount( - - } - /> - - ); - expect(wrapper).toMatchSnapshot(); - wrapper.find('button[aria-label="Close"]').simulate('click'); - expect(onClose).toBeCalled(); -}); diff --git a/packages/react-core/src/components/AlertGroup/__tests__/Generated/AlertGroup.test.tsx b/packages/react-core/src/components/AlertGroup/__tests__/Generated/AlertGroup.test.tsx deleted file mode 100644 index d7e7365f495..00000000000 --- a/packages/react-core/src/components/AlertGroup/__tests__/Generated/AlertGroup.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AlertGroup } from '../../AlertGroup'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AlertGroup should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode
      } isToast={true} appendTo={undefined} /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AlertGroup/__tests__/Generated/AlertGroupInline.test.tsx b/packages/react-core/src/components/AlertGroup/__tests__/Generated/AlertGroupInline.test.tsx deleted file mode 100644 index 97b0d4e81bb..00000000000 --- a/packages/react-core/src/components/AlertGroup/__tests__/Generated/AlertGroupInline.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { AlertGroupInline } from '../../AlertGroupInline'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('AlertGroupInline should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/AlertGroup/__tests__/Generated/__snapshots__/AlertGroup.test.tsx.snap b/packages/react-core/src/components/AlertGroup/__tests__/Generated/__snapshots__/AlertGroup.test.tsx.snap deleted file mode 100644 index f16bccf2e6f..00000000000 --- a/packages/react-core/src/components/AlertGroup/__tests__/Generated/__snapshots__/AlertGroup.test.tsx.snap +++ /dev/null @@ -1,16 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AlertGroup should match snapshot (auto-generated) 1`] = ` -} -> - -
      - ReactNode -
      -
      -
      -`; diff --git a/packages/react-core/src/components/AlertGroup/__tests__/Generated/__snapshots__/AlertGroupInline.test.tsx.snap b/packages/react-core/src/components/AlertGroup/__tests__/Generated/__snapshots__/AlertGroupInline.test.tsx.snap deleted file mode 100644 index 6a36de3ff4f..00000000000 --- a/packages/react-core/src/components/AlertGroup/__tests__/Generated/__snapshots__/AlertGroupInline.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AlertGroupInline should match snapshot (auto-generated) 1`] = ` -
        -`; diff --git a/packages/react-core/src/components/AlertGroup/__tests__/__snapshots__/AlertGroup.test.tsx.snap b/packages/react-core/src/components/AlertGroup/__tests__/__snapshots__/AlertGroup.test.tsx.snap deleted file mode 100644 index c6b4d1486fc..00000000000 --- a/packages/react-core/src/components/AlertGroup/__tests__/__snapshots__/AlertGroup.test.tsx.snap +++ /dev/null @@ -1,812 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Alert Group should match snapshot 1`] = ``; - -exports[`Standard Alert Group is not a toast alert group 1`] = ` - - -
          -
        • - -
          - -
          - - - - - -
          -
          -

          - - Danger alert: - - alert title -

          -
          -
          -
        • -
        -
        -
        -`; - -exports[`Toast Alert Group contains expected modifier class 1`] = ` - - -
          -
        • -
          -
          - -
          -

          - - Warning alert: - - alert title -

          - -
          -
        • -
        -
      - } - > - -
        -
      • - -
        - -
        - - - - - -
        -
        -

        - - Warning alert: - - alert title -

        -
        -
        -
      • -
      -
      - - -`; - -exports[`alertgroup closes when alerts are closed 1`] = ` - -
      -
      -
      -
      -
      -
        -
      • -
        -
        - -
        -

        - - Warning alert: - - alert title -

        - -
        -
      • -
      -
      -
      -
      -
        -
      • -
        -
        - -
        -

        - - Default alert: - - Test Alert -

        -
        - -
        - -
        -
      • -
      -
      - - } - isToast={true} -> - -
        -
      • -
        -
        - -
        -

        - - Default alert: - - Test Alert -

        -
        - -
        - -
        -
      • -
      -
      - } - > - -
      -
      -
      -
      -
      -
        -
      • -
        -
        - -
        -

        - - Warning alert: - - alert title -

        - -
        -
      • -
      -
      -
      -
      -
        -
      • -
        -
        - -
        -

        - - Default alert: - - Test Alert -

        -
        - -
        - -
        -
      • -
      -
      - - } - isToast={true} - > -
        -
        -
        -
        -
        -
        -
          -
        • -
          -
          - -
          -

          - - Warning alert: - - alert title -

          - -
          -
        • -
        -
        -
        -
        -
          -
        • -
          -
          - -
          -

          - - Default alert: - - Test Alert -

          -
          - -
          - -
          -
        • -
        -
        - - } - aria-atomic={null} - aria-live={null} - className="pf-c-alert-group pf-m-toast" - > -
      • - - } - isLiveRegion={true} - key=".0" - title="Test Alert" - > -
        - -
        - - - - - -
        -
        -

        - - Default alert: - - Test Alert -

        -
        - - - - - -
        -
        -
        -
      • -
      - - - -`; diff --git a/packages/react-core/src/components/AlertGroup/examples/AlertGroup.md b/packages/react-core/src/components/AlertGroup/examples/AlertGroup.md deleted file mode 100644 index d76183926c2..00000000000 --- a/packages/react-core/src/components/AlertGroup/examples/AlertGroup.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -id: Alert group -section: components -cssPrefix: pf-c-alert-group -propComponents: ['Alert', 'AlertGroup', 'AlertActionCloseButton', 'AlertActionLink'] ---- - -## Examples -### Static alert group -These alerts appear on page load and are discoverable from within the normal page content flow, and will not be announced individually/explicitly to assistive technology. -```js -import React from 'react'; -import { Alert, AlertGroup } from '@patternfly/react-core'; - -class StaticAlertGroup extends React.Component { - render() { - return ( - - - - - - - ); - } -} -``` - -### Toast alert group -Alerts asynchronously appended into dynamic AlertGroups with `isLiveRegion` will be announced to assistive technology at the moment the change happens, following the strategy used for aria-atomic, which defaults to false. This means only changes of type "addition" will be announced. -```js -import React from 'react'; -import { Alert, AlertGroup, AlertActionCloseButton, AlertVariant, InputGroup } from '@patternfly/react-core'; -class ToastAlertGroup extends React.Component { - constructor() { - super(); - this.state = { alerts: [] }; - this.addAlert = (title, variant, key) => { - this.setState({ - alerts: [ ...this.state.alerts, { title: title, variant: variant, key }] - }); - }; - this.removeAlert = key => { - this.setState({ alerts: [...this.state.alerts.filter(el => el.key !== key)] }); - }; - } - render() { - const btnClasses = ['pf-c-button', 'pf-m-secondary'].join(' '); - const getUniqueId = () => (new Date().getTime()); - const addSuccessAlert = () => { this.addAlert('Toast success alert', 'success', getUniqueId()) }; - const addDangerAlert = () => { this.addAlert('Toast danger alert', 'danger', getUniqueId()) }; - const addInfoAlert = () => { this.addAlert('Toast info alert', 'info', getUniqueId()) }; - return ( - - - - - - - - {this.state.alerts.map(({key, variant, title}) => ( - this.removeAlert(key)} - /> - } - key={key} /> - ))} - - - ); - } -} -``` - -### Singular dynamic alert group -This alert will appear in the page, most likely in response to a user action. -```js -import React from 'react'; -import { Alert, AlertGroup, AlertVariant, AlertActionCloseButton, InputGroup } from '@patternfly/react-core'; -class SingularAdditiveAlertGroup extends React.Component { - constructor() { - super(); - this.state = { - alerts: [] - } - } - render() { - const addAlert = (title, variant, key) => { - this.setState({ alerts: [...this.state.alerts, { title: title, variant: variant, key }] }); - }; - const btnClasses = ['pf-c-button', 'pf-m-secondary'].join(' '); - const getUniqueId = () => (new Date().getTime()); - const addSuccessAlert = () => { addAlert('Single success alert', 'success', getUniqueId()) }; - const addDangerAlert = () => { addAlert('Single danger alert', 'danger', getUniqueId()) }; - const addInfoAlert = () => { addAlert('Single info alert', 'info', getUniqueId()) }; - this.removeAlert = key => { - this.setState({ alerts: [...this.state.alerts.filter(el => el.key !== key)] }); - }; - return ( - - - - - - - - {this.state.alerts.map(({ title, variant, key }) => ( - this.removeAlert(key)} - /> - }/> - ))} - - - ); - } -} -``` - -### Multiple dynamic alert group -These alerts will appear in the page, most likely in response to a user action. -```js -import React from 'react'; -import { Alert, AlertGroup, AlertVariant, AlertActionCloseButton, InputGroup } from '@patternfly/react-core'; -class MultipleAdditiveAlertGroup extends React.Component { - constructor() { - super(); - this.state = { - alerts: [] - } - } - render() { - const addAlerts = (incomingAlerts) => { - this.setState({ alerts: [...this.state.alerts, ...incomingAlerts] }); - }; - const getUniqueId = () => ( - (String.fromCharCode(65 + Math.floor(Math.random() * 26))+ Date.now()) - ); - const btnClasses = ['pf-c-button', 'pf-m-secondary'].join(' '); - const addAlertCollection = () => { - addAlerts([ - { title: 'First alert notification.', variant: 'success', key: getUniqueId() }, - { title: 'Second alert notification.', variant: 'warning', key: getUniqueId() }, - { title: 'Third alert notification.', variant: 'danger', key: getUniqueId() } - ]) - }; - this.removeAlert = key => { - this.setState({ alerts: [...this.state.alerts.filter(el => el.key !== key)] }); - }; - return ( - - - - - - {this.state.alerts.map(({ title, variant, key, action }) => ( - this.removeAlert(key)} - /> - }/> - ))} - - - ); - } -} -``` - -### Async alert group -This shows how an alert could be triggered by an asynchronous event in the application. Note how you can customize how the alert will be announced to assistive technology. See the alert group accessibility tab for more information. -```js -import React from 'react'; -import { Alert, AlertGroup, AlertActionCloseButton, AlertVariant, InputGroup } from '@patternfly/react-core'; -class AsyncAdditiveAlertGroup extends React.Component { - constructor() { - super(); - this.state = { - alerts: [], - timer: null - } - this.stopAsyncAlerts = () => { clearInterval(this.state.timer); } - } - componentWillUnmount() { this.stopAsyncAlerts(); } - render() { - const addAlerts = (incomingAlerts) => { this.setState({ alerts: [...this.state.alerts, ...incomingAlerts] }); }; - const getUniqueId = () => (new Date().getTime()); - const btnClasses = ['pf-c-button', 'pf-m-secondary'].join(' '); - this.removeAlert = key => { - this.setState({ alerts: [...this.state.alerts.filter(el => el.key !== key)] }); - }; - const startAsyncAlerts = () => { - let timerValue = setInterval(() => { - addAlerts([ - { - title: `Async notification ${this.state.alerts.length + 1} was added to the queue.`, - variant: 'danger', - key: getUniqueId() - } - ]) - }, 4500); - this.setState({timer: timerValue}); - }; - return ( - - - - - - - {this.state.alerts.map(({ title, variant, key }) => ( - this.removeAlert(key)} - /> - }/> - ))} - - - ); - } -} -``` diff --git a/packages/react-core/src/components/AlertGroup/index.ts b/packages/react-core/src/components/AlertGroup/index.ts deleted file mode 100644 index 02e94577fcb..00000000000 --- a/packages/react-core/src/components/AlertGroup/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AlertGroup } from './AlertGroup'; diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncher.tsx b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncher.tsx deleted file mode 100644 index 6b8566b7ed5..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncher.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/AppLauncher/app-launcher'; -import formStyles from '@patternfly/react-styles/css/components/FormControl/form-control'; -import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon'; -import { DropdownDirection, DropdownPosition, DropdownToggle, DropdownContext } from '../Dropdown'; -import { DropdownWithContext } from '../Dropdown/DropdownWithContext'; -import { ApplicationLauncherGroup } from './ApplicationLauncherGroup'; -import { ApplicationLauncherSeparator } from './ApplicationLauncherSeparator'; -import { ApplicationLauncherItem } from './ApplicationLauncherItem'; -import { ApplicationLauncherContext } from './ApplicationLauncherContext'; -import { ToggleMenuBaseProps } from '../../helpers/Popper/Popper'; -import { createRenderableFavorites, extendItemsWithFavorite } from '../../helpers/favorites'; - -export interface ApplicationLauncherProps extends ToggleMenuBaseProps, React.HTMLProps { - /** Additional element css classes */ - className?: string; - /** Display menu above or below dropdown toggle */ - direction?: DropdownDirection | 'up' | 'down'; - /** Array of application launcher items */ - items?: React.ReactNode[]; - /** Render Application launcher toggle as disabled icon */ - isDisabled?: boolean; - /** open bool */ - isOpen?: boolean; - /** Indicates where menu will be alligned horizontally */ - position?: DropdownPosition | 'right' | 'left'; - /** Function callback called when user selects item */ - onSelect?: (event: any) => void; - /** Callback called when application launcher toggle is clicked */ - onToggle?: (value: boolean) => void; - /** Adds accessible text to the button. Required for plain buttons */ - 'aria-label'?: string; - /** Flag to indicate if application launcher has groups */ - isGrouped?: boolean; - /** Toggle Icon, optional to override the icon used for the toggle */ - toggleIcon?: React.ReactNode; - /** ID list of favorited ApplicationLauncherItems */ - favorites?: string[]; - /** Enables favorites. Callback called when an ApplicationLauncherItem's favorite button is clicked */ - onFavorite?: (itemId: string, isFavorite: boolean) => void; - /** Enables search. Callback called when text input is entered into search box */ - onSearch?: (textInput: string) => void; - /** Placeholder text for search input */ - searchPlaceholderText?: string; - /** Text for search input when no results are found */ - searchNoResultsText?: string; - /** Additional properties for search input */ - searchProps?: any; - /** Label for the favorites group */ - favoritesLabel?: string; - /** ID of toggle */ - toggleId?: string; -} - -export class ApplicationLauncher extends React.Component { - static displayName = 'ApplicationLauncher'; - static defaultProps: ApplicationLauncherProps = { - className: '', - isDisabled: false, - direction: DropdownDirection.down, - favorites: [] as string[], - isOpen: false, - position: DropdownPosition.left, - /* eslint-disable @typescript-eslint/no-unused-vars */ - onSelect: (_event: any): any => undefined, - onToggle: (_value: boolean): any => undefined, - /* eslint-enable @typescript-eslint/no-unused-vars */ - 'aria-label': 'Application launcher', - isGrouped: false, - toggleIcon: , - searchPlaceholderText: 'Filter by name...', - searchNoResultsText: 'No results found', - favoritesLabel: 'Favorites', - menuAppendTo: 'inline' - }; - - createSearchBox = () => { - const { onSearch, searchPlaceholderText, searchProps } = this.props; - - return ( -
      - onSearch(e.target.value)} - {...searchProps} - > - } - > -
      - ); - }; - - render() { - const { - 'aria-label': ariaLabel, - isOpen, - onToggle, - toggleIcon, - toggleId, - onSelect, - isDisabled, - className, - isGrouped, - favorites, - onFavorite, - onSearch, - items, - /* eslint-disable @typescript-eslint/no-unused-vars */ - searchPlaceholderText, - searchProps, - ref, - /* eslint-enable @typescript-eslint/no-unused-vars */ - favoritesLabel, - searchNoResultsText, - menuAppendTo, - ...props - } = this.props; - let renderableItems: React.ReactNode[] = []; - - if (onFavorite) { - let favoritesGroup: React.ReactNode[] = []; - let renderableFavorites: React.ReactNode[] = []; - if (favorites.length > 0) { - renderableFavorites = createRenderableFavorites(items, isGrouped, favorites, true); - favoritesGroup = [ - - {renderableFavorites} - - - ]; - } - if (renderableFavorites.length > 0) { - renderableItems = favoritesGroup.concat(extendItemsWithFavorite(items, isGrouped, favorites)); - } else { - renderableItems = extendItemsWithFavorite(items, isGrouped, favorites); - } - } else { - renderableItems = items; - } - - if (items.length === 0) { - renderableItems = [ - - {searchNoResultsText} - - ]; - } - if (onSearch) { - renderableItems = [this.createSearchBox(), ...renderableItems]; - } - - return ( - - - - {toggleIcon} - - } - isGrouped={isGrouped} - /> - - - ); - } -} diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherContent.tsx b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherContent.tsx deleted file mode 100644 index 0aa45676ec9..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherContent.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/AppLauncher/app-launcher'; -import accessibleStyles from '@patternfly/react-styles/css/utilities/Accessibility/accessibility'; -import { ApplicationLauncherIcon } from './ApplicationLauncherIcon'; -import { ApplicationLauncherText } from './ApplicationLauncherText'; -import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; -import { ApplicationLauncherItemContext } from './ApplicationLauncherItemContext'; - -export interface ApplicationLauncherContentProps { - /** Main content to be rendered */ - children: React.ReactNode; -} - -export const ApplicationLauncherContent: React.FunctionComponent = ({ - children -}: ApplicationLauncherContentProps) => ( - - {({ isExternal, icon }) => ( - <> - {icon && {icon}} - {icon ? {children} : children} - {isExternal && ( - <> - - - - (opens new window) - - )} - - )} - -); -ApplicationLauncherContent.displayName = 'ApplicationLauncherContent'; diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherContext.ts b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherContext.ts deleted file mode 100644 index 790ac1d01da..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherContext.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from 'react'; - -export const ApplicationLauncherContext = React.createContext({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onFavorite: (itemId: string, isFavorite: boolean) => {} -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherGroup.tsx b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherGroup.tsx deleted file mode 100644 index 7be51bf49d4..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherGroup.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import * as React from 'react'; -import { DropdownGroup, DropdownGroupProps } from '../Dropdown'; - -export const ApplicationLauncherGroup: React.FunctionComponent = ({ - children, - ...props -}: DropdownGroupProps) => {children}; -ApplicationLauncherGroup.displayName = 'ApplicationLauncherGroup'; diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherIcon.tsx b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherIcon.tsx deleted file mode 100644 index 32dccfab789..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/AppLauncher/app-launcher'; - -export interface ApplicationLauncherIconProps extends React.HTMLProps { - /** content rendered inside the icon container */ - children: React.ReactNode; - /** Additional classes added to the icon container */ - className?: string; -} - -export const ApplicationLauncherIcon: React.FunctionComponent = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - className = '', - children, - ...props -}: ApplicationLauncherIconProps) => ( - - {children} - -); -ApplicationLauncherIcon.displayName = 'ApplicationLauncherIcon'; diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherItem.tsx b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherItem.tsx deleted file mode 100644 index 98db6da18e6..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherItem.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/AppLauncher/app-launcher'; -import { DropdownItem, DropdownItemProps } from '../Dropdown'; -import { ApplicationLauncherContent } from './ApplicationLauncherContent'; -import { ApplicationLauncherContext } from './ApplicationLauncherContext'; -import { ApplicationLauncherItemContext } from './ApplicationLauncherItemContext'; -import StarIcon from '@patternfly/react-icons/dist/esm/icons/star-icon'; -import { getUniqueId } from '../../helpers/util'; - -export interface ApplicationLauncherItemProps { - /** Icon rendered before the text */ - icon?: React.ReactNode; - /** If clicking on the item should open the page in a separate window */ - isExternal?: boolean; - /** Tooltip to display when hovered over the item */ - tooltip?: React.ReactNode; - /** Additional tooltip props forwarded to the Tooltip component */ - tooltipProps?: any; - /** A ReactElement to render, or a string to use as the component tag. - * Example: component={Alert} - * Example: component="button" - */ - component?: React.ReactNode; - /** Flag indicating if the item is favorited */ - isFavorite?: boolean; - /** Aria label text for favoritable button when favorited */ - ariaIsFavoriteLabel?: string; - /** Aria label text for favoritable button when not favorited */ - ariaIsNotFavoriteLabel?: string; - /** ID of the item. Required for tracking favorites. */ - id?: string; - customChild?: React.ReactNode; - /** Flag indicating if hitting enter triggers an arrow down key press. Automatically passed to favorites list items. */ - enterTriggersArrowDown?: boolean; -} - -export const ApplicationLauncherItem: React.FunctionComponent = ({ - className = '', - id, - children, - icon = null, - isExternal = false, - href, - tooltip = null, - tooltipProps = null, - component = 'a', - isFavorite = null, - ariaIsFavoriteLabel = 'starred', - ariaIsNotFavoriteLabel = 'not starred', - customChild, - enterTriggersArrowDown = false, - ...props -}: ApplicationLauncherItemProps & DropdownItemProps) => ( - - - {({ onFavorite }) => ( - { - onFavorite((id || getUniqueId('app-launcher-option')).replace('favorite-', ''), isFavorite); - }} - > - - - ) - })} - {...props} - > - {children && {children}} - - )} - - -); -ApplicationLauncherItem.displayName = 'ApplicationLauncherItem'; diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherItemContext.ts b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherItemContext.ts deleted file mode 100644 index 668125bc63f..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherItemContext.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as React from 'react'; - -export const ApplicationLauncherItemContext = React.createContext({ isExternal: false, icon: null }); diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherSeparator.tsx b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherSeparator.tsx deleted file mode 100644 index 59ca4ac3aba..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherSeparator.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import * as React from 'react'; -import { DropdownSeparator, SeparatorProps } from '../Dropdown/DropdownSeparator'; - -export const ApplicationLauncherSeparator: React.FunctionComponent = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - children, - ...props -}: SeparatorProps) => ; -ApplicationLauncherSeparator.displayName = 'ApplicationLauncherSeparator'; diff --git a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherText.tsx b/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherText.tsx deleted file mode 100644 index 9dcc4fc6f09..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/ApplicationLauncherText.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -export interface ApplicationLauncherTextProps extends React.HTMLProps { - /** content rendered inside the text container */ - children: React.ReactNode; - /** Additional classes added to the text container */ - className?: string; -} - -export const ApplicationLauncherText: React.FunctionComponent = ({ - className = '', - children, - ...props -}: ApplicationLauncherTextProps) => ( - - {children} - -); -ApplicationLauncherText.displayName = 'ApplicationLauncherText'; diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/ApplicationLauncher.test.tsx b/packages/react-core/src/components/ApplicationLauncher/__tests__/ApplicationLauncher.test.tsx deleted file mode 100644 index 62a1f862017..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/ApplicationLauncher.test.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; -import { ApplicationLauncher } from '../ApplicationLauncher'; -import { ApplicationLauncherItem } from '../ApplicationLauncherItem'; - -import { DropdownPosition, DropdownDirection } from '../../Dropdown/dropdownConstants'; -import { ApplicationLauncherSeparator } from '../ApplicationLauncherSeparator'; - -const dropdownItems = [ - Link, - - Action - , - - Disabled Link - , - - Disabled Action - , - , - Separated Link, - - Separated Action - -]; - -describe('ApplicationLauncher', () => { - test('regular', () => { - const view = mount(); - expect(view).toMatchSnapshot(); - }); - - test('right aligned', () => { - const view = mount(); - expect(view).toMatchSnapshot(); - }); - - test('dropup', () => { - const view = mount(); - expect(view).toMatchSnapshot(); - }); - - test('dropup + right aligned', () => { - const view = mount( - - ); - expect(view).toMatchSnapshot(); - }); - - test('expanded', () => { - const view = mount(); - expect(view).toMatchSnapshot(); - }); - - test('custom icon', () => { - const view = mount( - } /> - ); - expect(view).toMatchSnapshot(); - }); -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncher.test.tsx b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncher.test.tsx deleted file mode 100644 index 9585bab61f9..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncher.test.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ApplicationLauncher } from '../../ApplicationLauncher'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ApplicationLauncher should match snapshot (auto-generated)', () => { - const view = shallow( - undefined} - onToggle={(_value: boolean): any => undefined} - aria-label={"'Application launcher'"} - isGrouped={false} - toggleIcon={
      ReactNode
      } - favorites={[]} - onFavorite={(itemId: string, isFavorite: boolean) => undefined as void} - onSearch={(textInput: string) => undefined as void} - searchPlaceholderText={"'Filter by name...'"} - searchNoResultsText={"'No results found'"} - searchProps={'any'} - favoritesLabel={"'Favorites'"} - toggleId={'string'} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherContent.test.tsx b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherContent.test.tsx deleted file mode 100644 index 153aa53ecdb..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherContent.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ApplicationLauncherContent } from '../../ApplicationLauncherContent'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ApplicationLauncherContent should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode
      } />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherGroup.test.tsx b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherGroup.test.tsx deleted file mode 100644 index 95ae6776964..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherGroup.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ApplicationLauncherGroup } from '../../ApplicationLauncherGroup'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ApplicationLauncherGroup should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherIcon.test.tsx b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherIcon.test.tsx deleted file mode 100644 index 07379514112..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherIcon.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ApplicationLauncherIcon } from '../../ApplicationLauncherIcon'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ApplicationLauncherIcon should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode
      } className={"''"} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherSeparator.test.tsx b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherSeparator.test.tsx deleted file mode 100644 index 615c1554954..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherSeparator.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ApplicationLauncherSeparator } from '../../ApplicationLauncherSeparator'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ApplicationLauncherSeparator should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherText.test.tsx b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherText.test.tsx deleted file mode 100644 index 90859c5ac8c..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/ApplicationLauncherText.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ApplicationLauncherText } from '../../ApplicationLauncherText'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ApplicationLauncherText should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode
      } className={"''"} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncher.test.tsx.snap b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncher.test.tsx.snap deleted file mode 100644 index 1705184b069..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncher.test.tsx.snap +++ /dev/null @@ -1,83 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ApplicationLauncher should match snapshot (auto-generated) 1`] = ` - - - - - } - /> -
      , - - - 'No results found' - - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="right" - toggle={ - -
      - ReactNode -
      -
      - } - /> - - -`; diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherContent.test.tsx.snap b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherContent.test.tsx.snap deleted file mode 100644 index 3f3369cc956..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherContent.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ApplicationLauncherContent should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherGroup.test.tsx.snap b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherGroup.test.tsx.snap deleted file mode 100644 index 10ed51b5935..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherGroup.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ApplicationLauncherGroup should match snapshot (auto-generated) 1`] = ``; diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherIcon.test.tsx.snap b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherIcon.test.tsx.snap deleted file mode 100644 index ecabf3ed8d2..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherIcon.test.tsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ApplicationLauncherIcon should match snapshot (auto-generated) 1`] = ` - -
      - ReactNode -
      -
      -`; diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherSeparator.test.tsx.snap b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherSeparator.test.tsx.snap deleted file mode 100644 index 31de6a2c872..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherSeparator.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ApplicationLauncherSeparator should match snapshot (auto-generated) 1`] = ``; diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherText.test.tsx.snap b/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherText.test.tsx.snap deleted file mode 100644 index 8a8df52826c..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/Generated/__snapshots__/ApplicationLauncherText.test.tsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ApplicationLauncherText should match snapshot (auto-generated) 1`] = ` - -
      - ReactNode -
      -
      -`; diff --git a/packages/react-core/src/components/ApplicationLauncher/__tests__/__snapshots__/ApplicationLauncher.test.tsx.snap b/packages/react-core/src/components/ApplicationLauncher/__tests__/__snapshots__/ApplicationLauncher.test.tsx.snap deleted file mode 100644 index 640fd44a78b..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/__tests__/__snapshots__/ApplicationLauncher.test.tsx.snap +++ /dev/null @@ -1,3149 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ApplicationLauncher custom icon 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - menuAppendTo="inline" - onSelect={[Function]} - onToggle={[Function]} - position="left" - searchNoResultsText="No results found" - searchPlaceholderText="Filter by name..." - toggleIcon={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={true} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - - - } - > - , - } - } - toggleIndicator={null} - > - - - - , - } - } - toggleVariant="default" - > - - - - - - - - - -`; - -exports[`ApplicationLauncher dropup + right aligned 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - menuAppendTo="inline" - onSelect={[Function]} - onToggle={[Function]} - position="right" - searchNoResultsText="No results found" - searchPlaceholderText="Filter by name..." - toggleIcon={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="right" - toggle={ - - - - } - > - , - } - } - toggleIndicator={null} - > - - - , - } - } - toggleVariant="default" - > - - - - - - -`; - -exports[`ApplicationLauncher dropup 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - menuAppendTo="inline" - onSelect={[Function]} - onToggle={[Function]} - position="left" - searchNoResultsText="No results found" - searchPlaceholderText="Filter by name..." - toggleIcon={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - - - } - > - , - } - } - toggleIndicator={null} - > - - - , - } - } - toggleVariant="default" - > - - - - - - -`; - -exports[`ApplicationLauncher expanded 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - menuAppendTo="inline" - onSelect={[Function]} - onToggle={[Function]} - position="left" - searchNoResultsText="No results found" - searchPlaceholderText="Filter by name..." - toggleIcon={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={true} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - - - } - > - , - } - } - toggleIndicator={null} - > - - - - , - } - } - toggleVariant="default" - > - - - - - - - - - -`; - -exports[`ApplicationLauncher regular 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - menuAppendTo="inline" - onSelect={[Function]} - onToggle={[Function]} - position="left" - searchNoResultsText="No results found" - searchPlaceholderText="Filter by name..." - toggleIcon={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - - - } - > - , - } - } - toggleIndicator={null} - > - - - , - } - } - toggleVariant="default" - > - - - - - - -`; - -exports[`ApplicationLauncher right aligned 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - menuAppendTo="inline" - onSelect={[Function]} - onToggle={[Function]} - position="right" - searchNoResultsText="No results found" - searchPlaceholderText="Filter by name..." - toggleIcon={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="right" - toggle={ - - - - } - > - , - } - } - toggleIndicator={null} - > - - - , - } - } - toggleVariant="default" - > - - - - - - -`; diff --git a/packages/react-core/src/components/ApplicationLauncher/examples/ApplicationLauncher.md b/packages/react-core/src/components/ApplicationLauncher/examples/ApplicationLauncher.md deleted file mode 100644 index a008f00bf58..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/examples/ApplicationLauncher.md +++ /dev/null @@ -1,632 +0,0 @@ ---- -id: Application launcher -section: components -cssPrefix: pf-c-app-launcher -propComponents: ['ApplicationLauncher', 'ApplicationLauncherItem', 'ApplicationLauncherContent'] -ouia: true ---- - -import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; -import { Link } from '@reach/router'; -import pfIcon from './pf-logo-small.svg'; - -Note: Application launcher is built on Dropdown, for extended API go to [Dropdown](/documentation/react/components/dropdown) documentation. -To add a tooltip, use the `tooltip` prop and optionally add more tooltip props by using `tooltipProps`. For more tooltip information go to [Tooltip](/documentation/react/components/tooltip). - -## Examples - -### Basic - -```js -import React from 'react'; -import { ApplicationLauncher, ApplicationLauncherItem } from '@patternfly/react-core'; - -class SimpleApplicationLauncher extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const appLauncherItems = [ - - Application 1 (anchor link) - , - alert('Clicked item 2')}> - Application 2 (button with onClick) - , - - Unavailable application - - ]; - return ( - - ); - } -} -``` - -### Router link - -```js -import React from 'react'; -import { Link } from '@reach/router'; -import { ApplicationLauncher, ApplicationLauncherItem, ApplicationLauncherContent, Text } from '@patternfly/react-core'; - -class SimpleApplicationLauncher extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const icon = ; - const exampleStyle = { - color: 'var(--pf-c-app-launcher__menu-item--Color)', - textDecoration: 'none' - }; - const appLauncherItems = [ - - @reach/router Link - - } - />, - - @reach/router Link with icon - - } - />, - - Application 1 (anchor link) - , - alert('Clicked item 2')}> - Application 2 (button with onClick) - , - - Unavailable application - - ]; - return ( - - ); - } -} -``` - -### Disabled - -```js -import React from 'react'; -import { ApplicationLauncher, ApplicationLauncherItem } from '@patternfly/react-core'; - -class SimpleApplicationLauncher extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const appLauncherItems = [ - - Application 1 (anchor link) - , - alert('Clicked item 2')}> - Application 2 (button with onClick) - , - - Unavailable application - - ]; - return ( - - ); - } -} -``` - -### Aligned right - -```js -import React from 'react'; -import { ApplicationLauncher, ApplicationLauncherItem } from '@patternfly/react-core'; -import { DropdownPosition } from '../Dropdown'; - -class SimpleApplicationLauncher extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const appLauncherItems = [ - - Application 1 (anchor link) - , - alert('Clicked item 2')}> - Application 2 (button with onClick) - , - - Unavailable application - - ]; - const style = { marginLeft: 'calc(100% - 46px)' }; - return ( - - ); - } -} -``` - -### Aligned top - -```js -import React from 'react'; -import { ApplicationLauncher, ApplicationLauncherItem } from '@patternfly/react-core'; -import { DropdownDirection } from '../Dropdown'; - -class SimpleApplicationLauncher extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const appLauncherItems = [ - - Application 1 (anchor link) - , - alert('Clicked item 2')}> - Application 2 (button with onClick) - , - - Unavailable application - - ]; - return ( - - ); - } -} -``` - -### With tooltip - -```js -import React from 'react'; -import { ApplicationLauncher, ApplicationLauncherItem } from '@patternfly/react-core'; - -class TooltipApplicationLauncher extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const appLauncherItems = [ - Launch Application 1
      }> - Application 1 (anchor link) - , - Launch Application 2
      } - tooltipProps={{ position: 'right' }} - onClick={() => alert('Clicked item 2')} - > - Application 2 (onClick) - , - Launch Application 3
      } - tooltipProps={{ position: 'bottom' }} - onClick={() => alert('Clicked item 3')} - > - Application 3 (onClick) - - ]; - return ( - - ); - } -} -``` - -### With sections and icons - -```js -import React from 'react'; -import { - ApplicationLauncher, - ApplicationLauncherItem, - ApplicationLauncherGroup, - ApplicationLauncherSeparator -} from '@patternfly/react-core'; -import pfIcon from './examples/pf-logo-small.svg'; - -class ApplicationLauncherSections extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const icon = ; - const appLauncherItems = [ - - - Item without group title - - - , - - - Group 2 button - - - Group 2 anchor link - - - , - - - Group 3 button - - - Group 3 anchor link - - - ]; - return ( - - ); - } -} -``` - -### With favorites and search - -```js -import React from 'react'; -import { - ApplicationLauncher, - ApplicationLauncherItem, - ApplicationLauncherGroup, - ApplicationLauncherSeparator -} from '@patternfly/react-core'; -import pfIcon from './examples/pf-logo-small.svg'; - -class ApplicationLauncherFavorites extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false, - favorites: [], - filteredItems: null - }; - - const icon = ; - this.appLauncherItems = [ - - - Item without group title - - - , - - - Group 2 button - - - Group 2 anchor link - - - , - - - Group 3 button - - - Group 3 anchor link - - - ]; - - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - this.onFavorite = (itemId, isFavorite) => { - if (isFavorite) { - this.setState({ - favorites: this.state.favorites.filter(id => id !== itemId) - }); - } else - this.setState({ - favorites: [...this.state.favorites, itemId] - }); - }; - this.onSearch = textInput => { - if (textInput === '') { - this.setState({ - filteredItems: null - }); - } else { - let filteredGroups = this.appLauncherItems - .map(group => { - let filteredGroup = React.cloneElement(group, { - children: group.props.children.filter(item => { - if (item.type === ApplicationLauncherSeparator) return item; - return item.props.children.toLowerCase().includes(textInput.toLowerCase()); - }) - }); - if ( - filteredGroup.props.children.length > 0 && - filteredGroup.props.children[0].type !== ApplicationLauncherSeparator - ) - return filteredGroup; - }) - .filter(newGroup => newGroup); - - if (filteredGroups.length > 0) { - let lastGroup = filteredGroups.pop(); - lastGroup = React.cloneElement(lastGroup, { - children: lastGroup.props.children.filter(item => item.type !== ApplicationLauncherSeparator) - }); - filteredGroups.push(lastGroup); - } - - this.setState({ - filteredItems: filteredGroups - }); - } - }; - } - - render() { - const { isOpen, favorites, filteredItems } = this.state; - return ( - - ); - } -} -``` - -### With custom icon - -```js -import React from 'react'; -import { ApplicationLauncher, ApplicationLauncherItem } from '@patternfly/react-core'; -import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; - -class ApplicationLauncheIcon extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const appLauncherItems = [ - - Application 1 (anchor link) - , - alert('Clicked item 2')}> - Application 2 (button with onClick) - , - - Unavailable application - - ]; - return ( - } - /> - ); - } -} -``` - -### Basic with menu appended to document body - -```js -import React from 'react'; -import { ApplicationLauncher, ApplicationLauncherItem } from '@patternfly/react-core'; - -class ApplicationLauncherDocumentBody extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const appLauncherItems = [ - - Application 1 (anchor link) - , - alert('Clicked item 2')}> - Application 2 (button with onClick) - , - - Unavailable application - - ]; - return ( - document.body} - onSelect={this.onSelect} - onToggle={this.onToggle} - isOpen={isOpen} - items={appLauncherItems} - /> - ); - } -} -``` diff --git a/packages/react-core/src/components/ApplicationLauncher/index.ts b/packages/react-core/src/components/ApplicationLauncher/index.ts deleted file mode 100644 index 9fa98e29991..00000000000 --- a/packages/react-core/src/components/ApplicationLauncher/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './ApplicationLauncher'; -export * from './ApplicationLauncherContext'; -export * from './ApplicationLauncherItem'; -export * from './ApplicationLauncherItemContext'; -export * from './ApplicationLauncherContent'; -export * from './ApplicationLauncherIcon'; -export * from './ApplicationLauncherText'; -export * from './ApplicationLauncherGroup'; -export * from './ApplicationLauncherSeparator'; diff --git a/packages/react-core/src/components/Avatar/Avatar.tsx b/packages/react-core/src/components/Avatar/Avatar.tsx index e1357e4761d..1f1c2f2cde5 100644 --- a/packages/react-core/src/components/Avatar/Avatar.tsx +++ b/packages/react-core/src/components/Avatar/Avatar.tsx @@ -1,35 +1,34 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Avatar/avatar'; import { css } from '@patternfly/react-styles'; -export interface AvatarProps - extends React.DetailedHTMLProps, HTMLImageElement> { - /** Additional classes added to the Avatar. */ +export interface AvatarProps extends React.DetailedHTMLProps< + React.ImgHTMLAttributes, + HTMLImageElement +> { + /** Additional classes added to the avatar. */ className?: string; - /** Attribute that specifies the URL of the image for the Avatar. */ + /** Attribute that specifies the URL of the image for the avatar. */ src?: string; - /** Attribute that specifies the alternate text of the image for the Avatar. */ + /** Attribute that specifies the alternate text of the image for the avatar. */ alt: string; - /** Border to add */ - border?: 'light' | 'dark'; + /** Flag to indicate the avatar should have a border. */ + isBordered?: boolean; + /** Size variant of avatar. */ + size?: 'sm' | 'md' | 'lg' | 'xl'; } export const Avatar: React.FunctionComponent = ({ - className = '', + className, src = '', alt, - border, + isBordered, + size, ...props }: AvatarProps) => ( {alt} ); diff --git a/packages/react-core/src/components/Avatar/__tests__/Avatar.test.tsx b/packages/react-core/src/components/Avatar/__tests__/Avatar.test.tsx index 538bfc3b1fc..8f3b066e074 100644 --- a/packages/react-core/src/components/Avatar/__tests__/Avatar.test.tsx +++ b/packages/react-core/src/components/Avatar/__tests__/Avatar.test.tsx @@ -1,8 +1,69 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { Avatar } from '../Avatar'; +import styles from '@patternfly/react-styles/css/components/Avatar/avatar'; -test('simple avatar', () => { - const view: any = shallow(); - expect(view).toMatchSnapshot(); +test('Renders simple avatar', () => { + render( +
      + +
      + ); + expect(screen.getByTestId('avatar').firstChild).toBeVisible(); +}); + +test('Renders without any modifier class when isBordered and size props are not passed', () => { + render(); + expect(screen.getByRole('img')).toHaveClass(styles.avatar, { exact: true }); +}); + +test('Renders with class name pf-m-bordered when isBordered is passed', () => { + render(); + expect(screen.getByRole('img')).toHaveClass('pf-m-bordered'); +}); + +test('Renders with class name pf-m-xl when "xl" is passed as size prop', () => { + render(); + expect(screen.getByRole('img')).toHaveClass('pf-m-xl'); +}); + +test('Renders with class name pf-m-lg when "lg" is passed as size prop', () => { + render(); + expect(screen.getByRole('img')).toHaveClass('pf-m-lg'); +}); + +test('Renders with class name pf-m-md when "md" is passed as size prop', () => { + render(); + expect(screen.getByRole('img')).toHaveClass('pf-m-md'); +}); + +test('Renders with class name pf-m-sm when "sm" is passed as size prop', () => { + render(); + expect(screen.getByRole('img')).toHaveClass('pf-m-sm'); +}); + +test('Renders with custom class name when className prop is passed', () => { + render(); + expect(screen.getByRole('img')).toHaveClass('test-class'); +}); + +test('Renders with passed src prop', () => { + render(); + const image = screen.getByRole('img') as HTMLImageElement; + expect(image.src).toMatch('test.png'); +}); + +test('Renders with passed alt prop', () => { + render(); + expect(screen.getByRole('img')).toHaveProperty('alt', 'avatar'); +}); + +test('Renders with passed aria-label prop', () => { + render(); + expect(screen.getByRole('img')).toHaveAccessibleName('Avatar test'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(); + + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Avatar/__tests__/Generated/Avatar.test.tsx b/packages/react-core/src/components/Avatar/__tests__/Generated/Avatar.test.tsx deleted file mode 100644 index 2c05f0cad60..00000000000 --- a/packages/react-core/src/components/Avatar/__tests__/Generated/Avatar.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Avatar } from '../../Avatar'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Avatar should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Avatar/__tests__/Generated/__snapshots__/Avatar.test.tsx.snap b/packages/react-core/src/components/Avatar/__tests__/Generated/__snapshots__/Avatar.test.tsx.snap deleted file mode 100644 index 1b2132522df..00000000000 --- a/packages/react-core/src/components/Avatar/__tests__/Generated/__snapshots__/Avatar.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Avatar should match snapshot (auto-generated) 1`] = ` -string -`; diff --git a/packages/react-core/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap b/packages/react-core/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap index 03a96671a2a..b6bfd9b345e 100644 --- a/packages/react-core/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap +++ b/packages/react-core/src/components/Avatar/__tests__/__snapshots__/Avatar.test.tsx.snap @@ -1,9 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`simple avatar 1`] = ` -avatar +exports[`Matches the snapshot 1`] = ` + + avatar + `; diff --git a/packages/react-core/src/components/Avatar/examples/Avatar.md b/packages/react-core/src/components/Avatar/examples/Avatar.md index 6869cba7847..75417fde012 100644 --- a/packages/react-core/src/components/Avatar/examples/Avatar.md +++ b/packages/react-core/src/components/Avatar/examples/Avatar.md @@ -1,39 +1,26 @@ --- id: Avatar section: components -cssPrefix: pf-c-avatar +cssPrefix: pf-v6-c-avatar propComponents: ['Avatar'] --- -import avatarImg from './avatarImg.svg'; -import avatarImgDark from './avatarImgDark.svg'; -import './example.css'; +import { Fragment } from 'react'; +import avatarImg from '../../assets/avatarImg.svg'; ## Examples + ### Basic -```ts -import React from 'react'; -import { Avatar } from '@patternfly/react-core'; -import avatarImg from './avatarImg.svg'; - +```ts file="./AvatarBasic.tsx" ``` -### Bordered - light -```ts -import React from 'react'; -import { Avatar } from '@patternfly/react-core'; -import avatarImg from './img_avatar.svg'; +### Bordered - +```ts file="./AvatarBordered.tsx" ``` -### Bordered - dark -```ts -import React from 'react'; -import { Avatar } from '@patternfly/react-core'; -import avatarImgDark from './img_avatar-dark.svg'; +### Size variations - +```ts file="./AvatarSizeVariations.tsx" ``` - diff --git a/packages/react-core/src/components/Avatar/examples/AvatarBasic.tsx b/packages/react-core/src/components/Avatar/examples/AvatarBasic.tsx new file mode 100644 index 00000000000..a166aceb2c3 --- /dev/null +++ b/packages/react-core/src/components/Avatar/examples/AvatarBasic.tsx @@ -0,0 +1,4 @@ +import { Avatar } from '@patternfly/react-core'; +import avatarImg from '../../assets/avatarImg.svg'; + +; diff --git a/packages/react-core/src/components/Avatar/examples/AvatarBordered.tsx b/packages/react-core/src/components/Avatar/examples/AvatarBordered.tsx new file mode 100644 index 00000000000..429589810e2 --- /dev/null +++ b/packages/react-core/src/components/Avatar/examples/AvatarBordered.tsx @@ -0,0 +1,4 @@ +import { Avatar } from '@patternfly/react-core'; +import avatarImg from '../../assets/avatarImg.svg'; + +; diff --git a/packages/react-core/src/components/Avatar/examples/AvatarSizeVariations.tsx b/packages/react-core/src/components/Avatar/examples/AvatarSizeVariations.tsx new file mode 100644 index 00000000000..05ae1781ecd --- /dev/null +++ b/packages/react-core/src/components/Avatar/examples/AvatarSizeVariations.tsx @@ -0,0 +1,21 @@ +import { Fragment } from 'react'; +import { Avatar } from '@patternfly/react-core'; +import avatarImg from '../../assets/avatarImg.svg'; + + + Small +
      + +
      + Medium +
      + +
      + Large +
      + +
      + Extra Large +
      + +
      ; diff --git a/packages/react-core/src/components/Avatar/examples/example.css b/packages/react-core/src/components/Avatar/examples/example.css deleted file mode 100644 index 34f148c579c..00000000000 --- a/packages/react-core/src/components/Avatar/examples/example.css +++ /dev/null @@ -1,3 +0,0 @@ -#ws-react-c-avatar-bordered---dark { - background: var(--pf-global--BackgroundColor--dark-100); -} diff --git a/packages/react-core/src/components/BackToTop/BackToTop.tsx b/packages/react-core/src/components/BackToTop/BackToTop.tsx index 9ba76372c72..7943c890f0e 100644 --- a/packages/react-core/src/components/BackToTop/BackToTop.tsx +++ b/packages/react-core/src/components/BackToTop/BackToTop.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; +import { forwardRef, useEffect, useState } from 'react'; import styles from '@patternfly/react-styles/css/components/BackToTop/back-to-top'; import { css } from '@patternfly/react-styles'; -import AngleUpIcon from '@patternfly/react-icons/dist/esm/icons/angle-up-icon'; +import RhMicronsCaretUpIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-up-icon'; import { canUseDOM } from '../../helpers/util'; import { Button } from '../Button'; @@ -10,7 +10,7 @@ interface BackToTopProps extends React.DetailedHTMLProps; /** Selector for the scrollable element to spy on. Not passing a selector defaults to spying on window scroll events. */ scrollableSelector?: string; @@ -26,25 +26,27 @@ const BackToTopBase: React.FunctionComponent = ({ isAlwaysVisible = false, ...props }: BackToTopProps) => { - const [visible, setVisible] = React.useState(isAlwaysVisible); - React.useEffect(() => { + const [visible, setVisible] = useState(isAlwaysVisible); + useEffect(() => { setVisible(isAlwaysVisible); }, [isAlwaysVisible]); - const [scrollElement, setScrollElement] = React.useState(null); + const [scrollElement, setScrollElement] = useState(null); const toggleVisible = () => { - const scrolled = scrollElement.scrollY ? scrollElement.scrollY : scrollElement.scrollTop; - if (!isAlwaysVisible) { - if (scrolled > 400) { - setVisible(true); - } else { - setVisible(false); + if (scrollElement) { + const scrolled = scrollElement.scrollY ? scrollElement.scrollY : scrollElement.scrollTop; + if (!isAlwaysVisible) { + if (scrolled > 400) { + setVisible(true); + } else { + setVisible(false); + } } } }; - React.useEffect(() => { + useEffect(() => { const hasScrollSpy = Boolean(scrollableSelector); if (hasScrollSpy) { const scrollEl = document.querySelector(scrollableSelector) as HTMLElement; @@ -69,7 +71,7 @@ const BackToTopBase: React.FunctionComponent = ({ scrollEl.removeEventListener('scroll', toggleVisible); }; } - }); + }, [scrollableSelector, toggleVisible]); const handleClick = () => { scrollElement.scrollTo({ top: 0, behavior: 'smooth' }); @@ -82,14 +84,14 @@ const BackToTopBase: React.FunctionComponent = ({ onClick={handleClick} {...props} > -
      ); }; -export const BackToTop = React.forwardRef((props: BackToTopProps, ref: React.Ref) => ( +export const BackToTop = forwardRef((props: BackToTopProps, ref: React.Ref) => ( )); BackToTop.displayName = 'BackToTop'; diff --git a/packages/react-core/src/components/BackToTop/__tests__/BackToTop.test.tsx b/packages/react-core/src/components/BackToTop/__tests__/BackToTop.test.tsx index d8150d6f9fb..958e73e1785 100644 --- a/packages/react-core/src/components/BackToTop/__tests__/BackToTop.test.tsx +++ b/packages/react-core/src/components/BackToTop/__tests__/BackToTop.test.tsx @@ -1,22 +1,153 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; +import { createRef, RefObject } from 'react'; +import { fireEvent, render, screen } from '@testing-library/react'; import { BackToTop } from '../BackToTop'; +import userEvent from '@testing-library/user-event'; +import styles from '@patternfly/react-styles/css/components/BackToTop/back-to-top'; -describe('BackToTop', () => { - test('verify basic', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); +jest.mock('../../Button'); - test('verify custom class', () => { - const view = mount(test); +test('Renders BackToTop', () => { + render( +
      + +
      + ); - expect(view).toMatchSnapshot(); - }); + expect(screen.getByTestId('backtotop').firstChild).toBeTruthy(); +}); - test('verify always show', () => { - const view = mount(test); +test('Renders with the default class', () => { + render(); - expect(view).toMatchSnapshot(); - }); -}); \ No newline at end of file + expect(screen.getByRole(`button`).parentElement).toHaveClass(styles.backToTop); +}); + +test('BackToTop is not yet visible', () => { + render(); + + expect(screen.getByRole(`button`).parentElement).toHaveClass('pf-m-hidden'); +}); + +test('BackToTop is visible after scrolling', () => { + render(); + + fireEvent.scroll(window, { target: { scrollY: 401 } }); + expect(screen.getByRole(`button`).parentElement).not.toHaveClass('pf-m-hidden'); +}); + +test('ScrollTo event is fired after clicking BackToTop', async () => { + render(); + const user = userEvent.setup(); + fireEvent.scroll(window, { target: { scrollY: 401 } }); + global.scrollTo = jest.fn(); + + await user.click(screen.getByRole(`button`).parentElement as Element); + expect(global.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' }); +}); + +test('BackToTop gets hidden again after user scrolls back up', () => { + render(); + + fireEvent.scroll(window, { target: { scrollY: 401 } }); + + fireEvent.scroll(window, { target: { scrollY: 0 } }); + expect(screen.getByRole(`button`).parentElement).toHaveClass('pf-m-hidden'); +}); + +test('Renders BackToTop when isAlwaysVisible prop is set', () => { + render(); + + expect(screen.getByRole(`button`).parentElement).not.toHaveClass('pf-m-hidden'); +}); + +test('Renders with custom className prop passed', () => { + render(); + expect(screen.getByRole(`button`).parentElement).toHaveClass('test-class'); +}); + +test('Renders with custom title prop passed', () => { + render(); + expect(screen.getByRole(`button`).parentElement).toHaveTextContent('Back to the Future'); +}); + +test('Renders with passed aria-label', () => { + render(); + expect(screen.getByRole(`button`).parentElement).toHaveAccessibleName('Back to top test'); +}); + +test('BackToTop can be accessed via passed innerRef', () => { + const testRef: RefObject = createRef(); + render(); + global.scrollTo = jest.fn(); + testRef.current?.click(); + expect(global.scrollTo).toBeCalledTimes(1); +}); + +test('BackToTop reacts to scrolling inside element passed via scrollableSelector', () => { + render( +
      + +
      + ); + const wrapper = document.getElementById('backToTopWrapper'); + fireEvent.scroll(wrapper as HTMLElement, { target: { scrollY: 401 } }); + + expect(screen.getByRole(`button`).parentElement).not.toHaveClass('pf-m-hidden'); +}); + +test('BackToTop does not react to scrolling inside window when scrollableSelector passed', () => { + render( +
      + +
      + ); + fireEvent.scroll(window, { target: { scrollY: 401 } }); + + expect(screen.getByRole(`button`).parentElement).toHaveClass('pf-m-hidden'); +}); + +test('Clicking backToTop scrolls back to top of the element passed via scrollableSelector', async () => { + render( +
      + +
      + ); + const user = userEvent.setup(); + const wrapper = document.getElementById('backToTopWrapper'); + fireEvent.scroll(wrapper as HTMLElement, { target: { scrollY: 401 } }); + + wrapper!.scrollTo = jest.fn(); + await user.click(screen.getByRole(`button`).parentElement as Element); + + expect(wrapper?.scrollTo).toHaveBeenCalledTimes(1); +}); + +test('Passes correct text content to button child component', () => { + render(); + + expect(screen.getByText('Back to the future')).toBeVisible(); +}); + +test('Passes correct variant to button child component', () => { + render(); + + expect(screen.getByText('variant: primary')).toBeVisible(); +}); + +test('Passes correct iconPosition to button child component', () => { + render(); + + expect(screen.getByText('iconPosition: end')).toBeVisible(); +}); + +test('Passes correct icon to button child component', () => { + render(); + + expect(screen.getByTestId('icon').firstChild).toBeTruthy(); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/BackToTop/__tests__/__snapshots__/BackToTop.test.tsx.snap b/packages/react-core/src/components/BackToTop/__tests__/__snapshots__/BackToTop.test.tsx.snap index 48864199dfe..b290d087760 100644 --- a/packages/react-core/src/components/BackToTop/__tests__/__snapshots__/BackToTop.test.tsx.snap +++ b/packages/react-core/src/components/BackToTop/__tests__/__snapshots__/BackToTop.test.tsx.snap @@ -1,179 +1,44 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`BackToTop verify always show 1`] = ` - - +
      -
      + Back to top + +

      + variant: primary +

      +

      - - - -

      - - -`; - -exports[`BackToTop verify basic 1`] = ` - -`; - -exports[`BackToTop verify custom class 1`] = ` - - + Test label +

      +

      + isInline: undefined +

      +

      + iconPosition: end +

      - - - + +
      -
      -
      +
      + `; diff --git a/packages/react-core/src/components/BackToTop/examples/BackToTop.css b/packages/react-core/src/components/BackToTop/examples/BackToTop.css index be127704d46..299d5e26a3b 100644 --- a/packages/react-core/src/components/BackToTop/examples/BackToTop.css +++ b/packages/react-core/src/components/BackToTop/examples/BackToTop.css @@ -1,4 +1,4 @@ #ws-react-c-back-to-top-basic { - height: 300px; - position: relative; -} \ No newline at end of file + height: 300px; + position: relative; +} diff --git a/packages/react-core/src/components/BackToTop/examples/BackToTop.md b/packages/react-core/src/components/BackToTop/examples/BackToTop.md index a7796d7b5d6..17e0107517a 100644 --- a/packages/react-core/src/components/BackToTop/examples/BackToTop.md +++ b/packages/react-core/src/components/BackToTop/examples/BackToTop.md @@ -1,9 +1,8 @@ --- id: Back to top section: components -cssPrefix: pf-c-back-to-top +cssPrefix: pf-v6-c-back-to-top propComponents: ['BackToTop'] -beta: true --- import './BackToTop.css' @@ -16,9 +15,5 @@ Back to top only shows after overflowing element has been scrolled 400px. ### Basic -```js -import React from 'react'; -import { BackToTop } from '@patternfly/react-core'; - - -``` \ No newline at end of file +```ts file="./BackToTopBasic.tsx" +``` diff --git a/packages/react-core/src/components/BackToTop/examples/BackToTopBasic.tsx b/packages/react-core/src/components/BackToTop/examples/BackToTopBasic.tsx new file mode 100644 index 00000000000..31190319b2d --- /dev/null +++ b/packages/react-core/src/components/BackToTop/examples/BackToTopBasic.tsx @@ -0,0 +1,3 @@ +import { BackToTop } from '@patternfly/react-core'; + +export const BackToTopBasic: React.FunctionComponent = () => ; diff --git a/packages/react-core/src/components/Backdrop/Backdrop.tsx b/packages/react-core/src/components/Backdrop/Backdrop.tsx index 2465d6d7775..c564a8b7f53 100644 --- a/packages/react-core/src/components/Backdrop/Backdrop.tsx +++ b/packages/react-core/src/components/Backdrop/Backdrop.tsx @@ -1,11 +1,10 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Backdrop/backdrop'; export interface BackdropProps extends React.HTMLProps { - /** content rendered inside the backdrop */ + /** Content rendered inside the backdrop */ children?: React.ReactNode; - /** additional classes added to the button */ + /** Additional classes added to the backdrop */ className?: string; } diff --git a/packages/react-core/src/components/Backdrop/__tests__/Backdrop.test.tsx b/packages/react-core/src/components/Backdrop/__tests__/Backdrop.test.tsx index 728171bbcce..927bf1a4c44 100644 --- a/packages/react-core/src/components/Backdrop/__tests__/Backdrop.test.tsx +++ b/packages/react-core/src/components/Backdrop/__tests__/Backdrop.test.tsx @@ -1,8 +1,42 @@ -import React from 'react'; -import { shallow } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { Backdrop } from '../Backdrop'; +import styles from '@patternfly/react-styles/css/components/Backdrop/backdrop'; -test('Backdrop Test', () => { - const view = shallow(Backdrop); - expect(view).toMatchSnapshot(); +test('Renders without children', () => { + render( +
      + +
      + ); + expect(screen.getByTestId('backdrop').firstChild).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with the ${styles.backdrop}`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.backdrop); +}); + +test(`Renders with only the class ${styles.backdrop} by default`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.backdrop, { exact: true }); +}); + +test('Renders with custom class name when className prop is passed', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('test-class'); +}); + +test('Renders with the inherited element props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('this is a simple backdrop'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Backdrop); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Backdrop/__tests__/Generated/Backdrop.test.tsx b/packages/react-core/src/components/Backdrop/__tests__/Generated/Backdrop.test.tsx deleted file mode 100644 index 2a6a03ea037..00000000000 --- a/packages/react-core/src/components/Backdrop/__tests__/Generated/Backdrop.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Backdrop } from '../../Backdrop'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Backdrop should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Backdrop/__tests__/Generated/__snapshots__/Backdrop.test.tsx.snap b/packages/react-core/src/components/Backdrop/__tests__/Generated/__snapshots__/Backdrop.test.tsx.snap deleted file mode 100644 index a52fcff0175..00000000000 --- a/packages/react-core/src/components/Backdrop/__tests__/Generated/__snapshots__/Backdrop.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Backdrop should match snapshot (auto-generated) 1`] = ` -
      - ReactNode -
      -`; diff --git a/packages/react-core/src/components/Backdrop/__tests__/__snapshots__/Backdrop.test.tsx.snap b/packages/react-core/src/components/Backdrop/__tests__/__snapshots__/Backdrop.test.tsx.snap index 6e317820ed9..9c7c1fe815e 100644 --- a/packages/react-core/src/components/Backdrop/__tests__/__snapshots__/Backdrop.test.tsx.snap +++ b/packages/react-core/src/components/Backdrop/__tests__/__snapshots__/Backdrop.test.tsx.snap @@ -1,9 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Backdrop Test 1`] = ` -
      - Backdrop -
      +exports[`Matches the snapshot 1`] = ` + +
      + Backdrop +
      +
      `; diff --git a/packages/react-core/src/components/Backdrop/examples/Backdrop.md b/packages/react-core/src/components/Backdrop/examples/Backdrop.md index f432236d922..f0e72adffee 100644 --- a/packages/react-core/src/components/Backdrop/examples/Backdrop.md +++ b/packages/react-core/src/components/Backdrop/examples/Backdrop.md @@ -1,27 +1,13 @@ --- id: Backdrop section: components -cssPrefix: pf-c-backdrop +cssPrefix: pf-v6-c-backdrop propComponents: ['Backdrop'] --- ## Examples -### Basic -```js isFullscreen -import React from 'react'; -import { Backdrop } from '@patternfly/react-core'; - - -``` -### With spinner -```js isFullscreen -import React from 'react'; -import { Backdrop, Spinner, Bullseye } from '@patternfly/react-core'; +### Basic - - - - - +```ts isFullscreen file="./BackdropBasic.tsx" ``` diff --git a/packages/react-core/src/components/Backdrop/examples/BackdropBasic.tsx b/packages/react-core/src/components/Backdrop/examples/BackdropBasic.tsx new file mode 100644 index 00000000000..6a56cbacb1d --- /dev/null +++ b/packages/react-core/src/components/Backdrop/examples/BackdropBasic.tsx @@ -0,0 +1,3 @@ +import { Backdrop } from '@patternfly/react-core'; + +export const BackdropBasic: React.FunctionComponent = () => ; diff --git a/packages/react-core/src/components/BackgroundImage/BackgroundImage.tsx b/packages/react-core/src/components/BackgroundImage/BackgroundImage.tsx index 2ce478feef0..ed7fb875985 100644 --- a/packages/react-core/src/components/BackgroundImage/BackgroundImage.tsx +++ b/packages/react-core/src/components/BackgroundImage/BackgroundImage.tsx @@ -1,77 +1,28 @@ -import * as React from 'react'; -import cssVar from '@patternfly/react-tokens/dist/esm/c_background_image_BackgroundImage'; -import cssVarName2x from '@patternfly/react-tokens/dist/esm/c_background_image_BackgroundImage_2x'; -import cssVarNameSm from '@patternfly/react-tokens/dist/esm/c_background_image_BackgroundImage_sm'; -import cssVarNameSm2x from '@patternfly/react-tokens/dist/esm/c_background_image_BackgroundImage_sm_2x'; -import cssVarNameLg from '@patternfly/react-tokens/dist/esm/c_background_image_BackgroundImage_lg'; -import cssVarNameFilter from '@patternfly/react-tokens/dist/esm/c_background_image_Filter'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/BackgroundImage/background-image'; +import cssBackgroundImage from '@patternfly/react-tokens/dist/esm/c_background_image_BackgroundImage'; -export interface BackgroundImageSrcMap { - xs: string; - xs2x: string; - sm: string; - sm2x: string; - lg: string; -} - -const defaultFilter = ( - - - - - - - - - -); - -export interface BackgroundImageProps extends Omit, 'src'> { - /** Additional classes added to the background. */ +export interface BackgroundImageProps extends React.HTMLProps { + /** The URL or file path of the image for the background */ + src: string; + /** Additional classes added to the background image. */ className?: string; - /** Override svg filter to use */ - filter?: React.ReactElement; - /** Override image styles using a string or BackgroundImageSrc */ - src: string | BackgroundImageSrcMap; } -let filterCounter = 0; - export const BackgroundImage: React.FunctionComponent = ({ className, src, - filter = defaultFilter, ...props -}: BackgroundImageProps) => { - const getUrlValue = (size: keyof BackgroundImageSrcMap) => { - if (typeof src === 'string') { - return `url(${src})`; - } else if (typeof src === 'object') { - return `url(${src[size]})`; +}: BackgroundImageProps) => ( +
      +); - return ''; - }; - - const filterNum = React.useMemo(() => filterCounter++, []); - const filterId = `patternfly-background-image-filter-overlay${filterNum}`; - const style = { - [cssVar.name]: getUrlValue('xs'), - [cssVarName2x.name]: getUrlValue('xs2x'), - [cssVarNameSm.name]: getUrlValue('sm'), - [cssVarNameSm2x.name]: getUrlValue('sm2x'), - [cssVarNameLg.name]: getUrlValue('lg'), - [cssVarNameFilter.name]: `url(#${filterId})` - } as React.CSSProperties; - - return ( -
      - - {React.cloneElement(filter, { id: filterId })} - -
      - ); -}; BackgroundImage.displayName = 'BackgroundImage'; diff --git a/packages/react-core/src/components/BackgroundImage/__tests__/BackgroundImage.test.tsx b/packages/react-core/src/components/BackgroundImage/__tests__/BackgroundImage.test.tsx index a154ae2000e..870c96469f1 100644 --- a/packages/react-core/src/components/BackgroundImage/__tests__/BackgroundImage.test.tsx +++ b/packages/react-core/src/components/BackgroundImage/__tests__/BackgroundImage.test.tsx @@ -1,21 +1,30 @@ +import { render, screen } from '@testing-library/react'; import { BackgroundImage } from '../BackgroundImage'; -import * as React from 'react'; -import { shallow } from 'enzyme'; +import styles from '@patternfly/react-styles/css/components/BackgroundImage/background-image'; +import cssBackgroundImage from '@patternfly/react-tokens/dist/esm/c_background_image_BackgroundImage'; -const images = { - 'lg': '/assets/images/pfbg_1200.jpg', - 'sm': '/assets/images/pfbg_768.jpg', - 'sm2x': '/assets/images/pfbg_768@2x.jpg', - 'xs': '/assets/images/pfbg_576.jpg', - 'xs2x': '/assets/images/pfbg_576@2x.jpg' -}; +test(`renders with default className ${styles.backgroundImage}`, () => { + render(); + expect(screen.getByTestId('test-id')).toHaveClass(styles.backgroundImage, { exact: true }); +}); + +test('spreads additional props', () => { + render(); + expect(screen.getByTestId('test-id')).toHaveProperty('lang'); +}); + +test('has src URL applied to style', () => { + render(); + expect(screen.getByTestId('test-id')).toHaveAttribute('style', `${cssBackgroundImage.name}: url(/image/url.png);`); +}); + +test('renders with custom className when one is provided', () => { + render(); -test('BackgroundImage', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + expect(screen.getByTestId('test-id')).toHaveClass('another-class'); }); -test('allows passing in a single string as the image src', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); +test('Matches the snapshot', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/BackgroundImage/__tests__/Generated/BackgroundImage.test.tsx b/packages/react-core/src/components/BackgroundImage/__tests__/Generated/BackgroundImage.test.tsx deleted file mode 100644 index f1a80c6eca8..00000000000 --- a/packages/react-core/src/components/BackgroundImage/__tests__/Generated/BackgroundImage.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { BackgroundImage } from '../../BackgroundImage'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('BackgroundImage should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/BackgroundImage/__tests__/Generated/__snapshots__/BackgroundImage.test.tsx.snap b/packages/react-core/src/components/BackgroundImage/__tests__/Generated/__snapshots__/BackgroundImage.test.tsx.snap deleted file mode 100644 index d0975ff4e90..00000000000 --- a/packages/react-core/src/components/BackgroundImage/__tests__/Generated/__snapshots__/BackgroundImage.test.tsx.snap +++ /dev/null @@ -1,54 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`BackgroundImage should match snapshot (auto-generated) 1`] = ` -
      - - - - - - - - - - - -
      -`; diff --git a/packages/react-core/src/components/BackgroundImage/__tests__/__snapshots__/BackgroundImage.test.tsx.snap b/packages/react-core/src/components/BackgroundImage/__tests__/__snapshots__/BackgroundImage.test.tsx.snap index cfb0643cf41..0c639252c91 100644 --- a/packages/react-core/src/components/BackgroundImage/__tests__/__snapshots__/BackgroundImage.test.tsx.snap +++ b/packages/react-core/src/components/BackgroundImage/__tests__/__snapshots__/BackgroundImage.test.tsx.snap @@ -1,107 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`BackgroundImage 1`] = ` -
      - - - - - - - - - - - -
      -`; - -exports[`allows passing in a single string as the image src 1`] = ` -
      - - - - - - - - - - - -
      +exports[`Matches the snapshot 1`] = ` + +
      + `; diff --git a/packages/react-core/src/components/BackgroundImage/examples/BackgroundImage.md b/packages/react-core/src/components/BackgroundImage/examples/BackgroundImage.md index f604346f1f7..63fb03aae01 100644 --- a/packages/react-core/src/components/BackgroundImage/examples/BackgroundImage.md +++ b/packages/react-core/src/components/BackgroundImage/examples/BackgroundImage.md @@ -1,32 +1,13 @@ --- id: Background image section: components -cssPrefix: pf-c-background-image +cssPrefix: pf-v6-c-background-image propComponents: ['BackgroundImage'] --- ## Examples + ### Basic -```js isFullscreen -import React from 'react'; -import { BackgroundImage } from '@patternfly/react-core'; -class SimpleBackgroundImage extends React.Component { - constructor(props) { - super(props); - /** - * Note: When using background-filter.svg, you must also include #image_overlay as the fragment identifier - */ - this.images = { - 'xs': '/assets/images/pfbg_576.jpg', - 'xs2x': '/assets/images/pfbg_576@2x.jpg', - 'sm': '/assets/images/pfbg_768.jpg', - 'sm2x': '/assets/images/pfbg_768@2x.jpg', - 'lg': '/assets/images/pfbg_1200.jpg' - }; - } - render() { - return ; - } -} +```ts isFullscreen file="./BackgroundImageBasic.tsx" ``` diff --git a/packages/react-core/src/components/BackgroundImage/examples/BackgroundImageBasic.tsx b/packages/react-core/src/components/BackgroundImage/examples/BackgroundImageBasic.tsx new file mode 100644 index 00000000000..52b2e7d3c0a --- /dev/null +++ b/packages/react-core/src/components/BackgroundImage/examples/BackgroundImageBasic.tsx @@ -0,0 +1,5 @@ +import { BackgroundImage } from '@patternfly/react-core'; + +export const BackgroundImageBasic: React.FunctionComponent = () => ( + +); diff --git a/packages/react-core/src/components/Badge/Badge.tsx b/packages/react-core/src/components/Badge/Badge.tsx index 47ecad18dab..8a625be02d3 100644 --- a/packages/react-core/src/components/Badge/Badge.tsx +++ b/packages/react-core/src/components/Badge/Badge.tsx @@ -1,10 +1,13 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Badge/badge'; export interface BadgeProps extends React.HTMLProps { + /** Text announced by screen readers to indicate the current content/status of the badge. */ + screenReaderText?: string; /** Adds styling to the badge to indicate it has been read */ isRead?: boolean; + /** Adds styling to the badge to indicate it is disabled */ + isDisabled?: boolean; /** content rendered inside the Badge */ children?: React.ReactNode; /** additional classes added to the Badge */ @@ -13,15 +16,23 @@ export interface BadgeProps extends React.HTMLProps { export const Badge: React.FunctionComponent = ({ isRead = false, + isDisabled = false, className = '', children = '', + screenReaderText, ...props }: BadgeProps) => ( {children} + {screenReaderText && {screenReaderText}} ); Badge.displayName = 'Badge'; diff --git a/packages/react-core/src/components/Badge/__tests__/Badge.test.tsx b/packages/react-core/src/components/Badge/__tests__/Badge.test.tsx index 48e143a3fcb..12654efc25b 100644 --- a/packages/react-core/src/components/Badge/__tests__/Badge.test.tsx +++ b/packages/react-core/src/components/Badge/__tests__/Badge.test.tsx @@ -1,10 +1,62 @@ +import { render, screen } from '@testing-library/react'; import { Badge } from '../Badge'; -import React from 'react'; -import { shallow } from 'enzyme'; - -Object.values([true, false]).forEach(isRead => { - test(`${isRead} Badge`, () => { - const view = shallow({isRead ? 'read' : 'unread'} Badge); - expect(view).toMatchSnapshot(); - }); +import styles from '@patternfly/react-styles/css/components/Badge/badge'; + +test('Renders without children', () => { + render( +
      + +
      + ); + expect(screen.getByTestId('badge').firstChild).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with class name ${styles.badge}`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.badge); +}); + +test(`Renders with class name ${styles.modifiers.unread} by default`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.unread); +}); + +test('Renders with class name pf-m-read when isRead prop is true', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-read'); +}); + +test(`Renders with class name ${styles.modifiers.disabled} when isDisabled prop is true`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.modifiers.disabled); +}); + +test('Does not render pf-v6-screen-reader class by default', () => { + render(Test); + expect(screen.getByText('Test')).not.toContainHTML(''); +}); + +test('Renders screenReaderText passed via prop', () => { + render(Test); + expect(screen.getByText('Custom screen reader text')).toBeInTheDocument(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders with inherited element props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Badge/__tests__/Generated/Badge.test.tsx b/packages/react-core/src/components/Badge/__tests__/Generated/Badge.test.tsx deleted file mode 100644 index 7c161c5b895..00000000000 --- a/packages/react-core/src/components/Badge/__tests__/Generated/Badge.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Badge } from '../../Badge'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Badge should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Badge/__tests__/Generated/__snapshots__/Badge.test.tsx.snap b/packages/react-core/src/components/Badge/__tests__/Generated/__snapshots__/Badge.test.tsx.snap deleted file mode 100644 index a1b95480f71..00000000000 --- a/packages/react-core/src/components/Badge/__tests__/Generated/__snapshots__/Badge.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Badge should match snapshot (auto-generated) 1`] = ` - -`; diff --git a/packages/react-core/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap b/packages/react-core/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap index b708b4756ac..2bda68be733 100644 --- a/packages/react-core/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap +++ b/packages/react-core/src/components/Badge/__tests__/__snapshots__/Badge.test.tsx.snap @@ -1,19 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`false Badge 1`] = ` - - unread - Badge - -`; - -exports[`true Badge 1`] = ` - - read - Badge - +exports[`Matches the snapshot 1`] = ` + + + Test + + `; diff --git a/packages/react-core/src/components/Badge/examples/Badge.css b/packages/react-core/src/components/Badge/examples/Badge.css new file mode 100644 index 00000000000..4258fb9e830 --- /dev/null +++ b/packages/react-core/src/components/Badge/examples/Badge.css @@ -0,0 +1,6 @@ +#ws-react-c-badge-read .pf-v6-c-badge, +#ws-react-c-badge-unread .pf-v6-c-badge, +#ws-react-c-badge-badge-as-toggle .pf-v6-c-badge { + margin-inline-end: var(--pf-t--global--spacer--xs); + margin-block-end: var(--pf-t--global--spacer--xs); +} \ No newline at end of file diff --git a/packages/react-core/src/components/Badge/examples/Badge.md b/packages/react-core/src/components/Badge/examples/Badge.md index 120603cd09e..75667fa6d6a 100644 --- a/packages/react-core/src/components/Badge/examples/Badge.md +++ b/packages/react-core/src/components/Badge/examples/Badge.md @@ -1,39 +1,26 @@ --- id: Badge section: components -cssPrefix: pf-c-badge +cssPrefix: pf-v6-c-badge propComponents: ['Badge'] --- +import { Fragment } from 'react'; +import './Badge.css'; + ## Examples + ### Read -```js -import React from 'react'; -import { Badge } from '@patternfly/react-core'; - - - 7 - {' '} - 24 - {' '} - 240 - {' '} - 999+ - + +```ts file="./BadgeRead.tsx" ``` ### Unread -```js -import React from 'react'; -import { Badge } from '@patternfly/react-core'; - - - 7 - {' '} - 24 - {' '} - 240 - {' '} - 999+ - + +```ts file="./BadgeUnread.tsx" +``` + +### Disabled + +```ts file="./BadgeDisabled.tsx" ``` diff --git a/packages/react-core/src/components/Badge/examples/BadgeDisabled.tsx b/packages/react-core/src/components/Badge/examples/BadgeDisabled.tsx new file mode 100644 index 00000000000..decc3995e63 --- /dev/null +++ b/packages/react-core/src/components/Badge/examples/BadgeDisabled.tsx @@ -0,0 +1,19 @@ +import { Fragment } from 'react'; +import { Badge } from '@patternfly/react-core'; + +export const BadgeRead: React.FunctionComponent = () => ( + + + 7 + + + 24 + + + 240 + + + 999+ + + +); diff --git a/packages/react-core/src/components/Badge/examples/BadgeRead.tsx b/packages/react-core/src/components/Badge/examples/BadgeRead.tsx new file mode 100644 index 00000000000..fd0ea5fc6ff --- /dev/null +++ b/packages/react-core/src/components/Badge/examples/BadgeRead.tsx @@ -0,0 +1,19 @@ +import { Fragment } from 'react'; +import { Badge } from '@patternfly/react-core'; + +export const BadgeRead: React.FunctionComponent = () => ( + + + 7 + + + 24 + + + 240 + + + 999+ + + +); diff --git a/packages/react-core/src/components/Badge/examples/BadgeUnread.tsx b/packages/react-core/src/components/Badge/examples/BadgeUnread.tsx new file mode 100644 index 00000000000..d327227d19d --- /dev/null +++ b/packages/react-core/src/components/Badge/examples/BadgeUnread.tsx @@ -0,0 +1,19 @@ +import { Fragment } from 'react'; +import { Badge } from '@patternfly/react-core'; + +export const BadgeUnread: React.FunctionComponent = () => ( + + + 7 + + + 24 + + + 240 + + + 999+ + + +); diff --git a/packages/react-core/src/components/Banner/Banner.tsx b/packages/react-core/src/components/Banner/Banner.tsx index 72f6125c0ed..3acce9ab700 100644 --- a/packages/react-core/src/components/Banner/Banner.tsx +++ b/packages/react-core/src/components/Banner/Banner.tsx @@ -1,35 +1,63 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Banner/banner'; import { css } from '@patternfly/react-styles'; +export type BannerColor = 'red' | 'orangered' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'purple'; + +export type BannerStatus = 'success' | 'warning' | 'danger' | 'info' | 'custom'; + export interface BannerProps extends React.HTMLProps { - /** Content rendered inside the banner */ + /** Content rendered inside the banner. */ children?: React.ReactNode; - /** Additional classes added to the banner */ + /** Additional classes added to the banner. */ className?: string; - /** Variant styles for the banner */ - variant?: 'default' | 'info' | 'danger' | 'success' | 'warning'; /** If set to true, the banner sticks to the top of its container */ isSticky?: boolean; + /** Text announced by screen readers to indicate the type of banner. This prop should only + * be passed in when the banner conveys status/severity. + */ + screenReaderText?: string; + /** Color options for the banner, will be overwritten by any applied using the status prop. */ + color?: BannerColor; + /** Status style options for the banner, will overwrite any color applied using the color prop. */ + status?: BannerStatus; +} +interface StatusBanner extends BannerProps { + color?: never; + status?: BannerStatus; } -export const Banner: React.FunctionComponent = ({ +interface NonStatusBanner extends BannerProps { + color?: BannerColor; + status?: never; +} + +export const Banner: React.FunctionComponent = ({ children, className, - variant = 'default', + screenReaderText, isSticky = false, + color, + status, ...props -}: BannerProps) => ( -
      - {children} -
      -); +}: BannerProps) => { + const getStatusOrColorModifier = () => { + if (status) { + return styles.modifiers[status]; + } + + if (color) { + return styles.modifiers[color]; + } + }; + + return ( +
      + {screenReaderText && {screenReaderText}} + {children} +
      + ); +}; Banner.displayName = 'Banner'; diff --git a/packages/react-core/src/components/Banner/__tests__/Banner.test.tsx b/packages/react-core/src/components/Banner/__tests__/Banner.test.tsx index 6f2adfc2329..83a5ee4b41f 100644 --- a/packages/react-core/src/components/Banner/__tests__/Banner.test.tsx +++ b/packages/react-core/src/components/Banner/__tests__/Banner.test.tsx @@ -1,25 +1,127 @@ +import { render, screen } from '@testing-library/react'; import { Banner } from '../Banner'; -import React from 'react'; -import { mount } from 'enzyme'; - -['default', 'info', 'success', 'warning', 'danger'].forEach( - (variant: 'default' | 'info' | 'success' | 'warning' | 'danger') => { - test(`${variant} banner`, () => { - const view = mount( - - {variant} Banner - - ); - expect(view).toMatchSnapshot(); - }); - } -); - -test(`sticky banner`, () => { - const view = mount( - - Sticky Banner - +import styles from '@patternfly/react-styles/css/components/Banner/banner'; + +test('Renders without children', () => { + render( +
      + +
      ); - expect(view).toMatchSnapshot(); + expect(screen.getByTestId('banner').firstChild).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + expect(screen.getByText('Test')).toBeVisible(); +}); + +test(`Renders with class name ${styles.banner}`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.banner); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders without any modifier class when color and status props are not passed', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.banner, { exact: true }); +}); + +test('Renders with class name pf-m-red when "red" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-red'); +}); + +test('Renders with class name pf-m-orangered when "orangered" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-orangered'); +}); + +test('Renders with class name pf-m-orange when "orange" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-orange'); +}); + +test('Renders with class name pf-m-yellow when "yellow" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-yellow'); +}); + +test('Renders with class name pf-m-green when "green" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-green'); +}); + +test('Renders with class name pf-m-teal when "teal" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-teal'); +}); + +test('Renders with class name pf-m-blue when "blue" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-blue'); +}); + +test('Renders with class name pf-m-purple when "purple" is passed to color prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-purple'); +}); + +test('Renders with class name pf-m-success when "success" is passed to status prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-success'); +}); + +test('Renders with class name pf-m-warning when "warning" is passed to status prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-warning'); +}); + +test('Renders with class name pf-m-danger when "danger" is passed to status prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-danger'); +}); + +test('Renders with class name pf-m-info when "info" is passed to status prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-info'); +}); + +test('Renders with class name pf-m-custom when "custom" is passed to status prop', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-custom'); +}); + +test('Does not render pf-v6-screen-reader class by default', () => { + render(Test); + expect(screen.getByText('Test')).not.toContainHTML(''); +}); + +test('Renders screenReaderText passed via prop', () => { + render(Test); + expect(screen.getByText('Custom screen reader text')).toBeInTheDocument(); +}); + +test('Renders without pf-m-sticky by default', () => { + render(Test); + expect(screen.getByText('Test')).not.toHaveClass('pf-m-sticky'); +}); + +test('Renders with class name pf-m-sticky when isSticky prop is passed', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-sticky'); +}); + +test('Renders with inherited element props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Banner/__tests__/__snapshots__/Banner.test.tsx.snap b/packages/react-core/src/components/Banner/__tests__/__snapshots__/Banner.test.tsx.snap index e699fc93e33..54a68cd2d49 100644 --- a/packages/react-core/src/components/Banner/__tests__/__snapshots__/Banner.test.tsx.snap +++ b/packages/react-core/src/components/Banner/__tests__/__snapshots__/Banner.test.tsx.snap @@ -1,90 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`danger banner 1`] = ` - +exports[`Matches the snapshot 1`] = ` +
      - danger - Banner + Test
      -
      -`; - -exports[`default banner 1`] = ` - -
      - default - Banner -
      -
      -`; - -exports[`info banner 1`] = ` - -
      - info - Banner -
      -
      -`; - -exports[`sticky banner 1`] = ` - -
      - Sticky Banner -
      -
      -`; - -exports[`success banner 1`] = ` - -
      - success - Banner -
      -
      -`; - -exports[`warning banner 1`] = ` - -
      - warning - Banner -
      -
      + `; diff --git a/packages/react-core/src/components/Banner/examples/Banner.md b/packages/react-core/src/components/Banner/examples/Banner.md index 8cc06de8a1e..b681cfdfa3f 100644 --- a/packages/react-core/src/components/Banner/examples/Banner.md +++ b/packages/react-core/src/components/Banner/examples/Banner.md @@ -1,26 +1,34 @@ --- id: Banner section: components -cssPrefix: pf-c-banner +cssPrefix: pf-v6-c-banner propComponents: ['Banner'] --- +import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; +import RhUiErrorFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-error-fill-icon'; +import RhUiWarningFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-warning-fill-icon'; +import RhUiInformationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-information-fill-icon'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; + ## Examples ### Basic -```js -import React from 'react'; -import { Banner } from '@patternfly/react-core'; - - - Default banner -
      - Info banner -
      - Danger banner -
      - Success banner -
      - Warning banner -
      + +Banners can be styled with one of 9 different colors using the `color` prop. A basic banner should only be used when the banner color does not represent status or severity. + +```ts file="./BannerBasic.tsx" + +``` + +### Status + +When a banner is used to convey status it should be styled using the `status` prop. Additionally, it is advised to pass an icon inside the banner to convey the status in a way besides just color. + +The `screenReaderText` prop should also be passed in to convey the status/severity of the banner to users of certain assistive technologies such as screen readers. + +In the following example, a flex layout is used inside the banner content to show one possible way to create spacing between the icons and banner text. + +```ts file="./BannerStatus.tsx" + ``` diff --git a/packages/react-core/src/components/Banner/examples/BannerBasic.tsx b/packages/react-core/src/components/Banner/examples/BannerBasic.tsx new file mode 100644 index 00000000000..dae3a5c5af0 --- /dev/null +++ b/packages/react-core/src/components/Banner/examples/BannerBasic.tsx @@ -0,0 +1,23 @@ +import { Banner } from '@patternfly/react-core'; + +export const BannerBasic: React.FunctionComponent = () => ( + <> + Default banner +
      + Red banner +
      + Orangered banner +
      + Orange banner +
      + Yellow banner +
      + Green banner +
      + Teal banner +
      + Blue banner +
      + Purple banner + +); diff --git a/packages/react-core/src/components/Banner/examples/BannerStatus.tsx b/packages/react-core/src/components/Banner/examples/BannerStatus.tsx new file mode 100644 index 00000000000..f72e191496c --- /dev/null +++ b/packages/react-core/src/components/Banner/examples/BannerStatus.tsx @@ -0,0 +1,55 @@ +import { Banner, Flex, FlexItem } from '@patternfly/react-core'; +import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; +import RhUiErrorFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-error-fill-icon'; +import RhUiWarningFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-warning-fill-icon'; +import RhUiInformationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-information-fill-icon'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; + +export const BannerStatus: React.FunctionComponent = () => ( + <> + + + + + + Success banner + + +
      + + + + + + Warning banner + + +
      + + + + + + Danger banner + + +
      + + + + + + Info banner + + +
      + + + + + + Custom banner + + + +); diff --git a/packages/react-core/src/components/Brand/Brand.tsx b/packages/react-core/src/components/Brand/Brand.tsx index a326f511f5b..02c3695a9d4 100644 --- a/packages/react-core/src/components/Brand/Brand.tsx +++ b/packages/react-core/src/components/Brand/Brand.tsx @@ -1,18 +1,85 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Brand/brand'; +import { setBreakpointCssVars } from '../../helpers'; +import cssBrandHeight from '@patternfly/react-tokens/dist/esm/c_brand_Height'; +import cssBrandWidth from '@patternfly/react-tokens/dist/esm/c_brand_Width'; -export interface BrandProps - extends React.DetailedHTMLProps, HTMLImageElement> { - /** Additional classes added to the Brand. */ +export interface BrandProps extends React.DetailedHTMLProps< + React.ImgHTMLAttributes, + HTMLImageElement +> { + /** Transforms the Brand into a element from an element. Container for child elements. */ + children?: React.ReactNode; + /** Additional classes added to the either type of Brand. */ className?: string; - /** Attribute that specifies the URL of the image for the Brand. */ + /** Attribute that specifies the URL of a Brand. For a Brand this specifies the fallback URL. */ src?: string; - /** Attribute that specifies the alt text of the image for the Brand. */ + /** Attribute that specifies the alt text of a Brand. For a Brand this specifies the fallback alt text. */ alt: string; + /** Widths at various breakpoints for a Brand. */ + widths?: { + default?: string; + sm?: string; + md?: string; + lg?: string; + xl?: string; + '2xl'?: string; + }; + /** Heights at various breakpoints for a Brand. */ + heights?: { + default?: string; + sm?: string; + md?: string; + lg?: string; + xl?: string; + '2xl'?: string; + }; } -export const Brand: React.FunctionComponent = ({ className = '', src = '', alt, ...props }: BrandProps) => ( - /** the brand component currently contains no styling the 'pf-c-brand' string will be used for the className */ - {alt} -); +export const Brand: React.FunctionComponent = ({ + className = '', + src = '', + alt, + children, + widths, + heights, + style, + ...props +}: BrandProps) => { + let responsiveStyles; + if (widths !== undefined) { + responsiveStyles = { + ...setBreakpointCssVars(widths, cssBrandWidth.name) + }; + } + + if (heights !== undefined) { + responsiveStyles = { + ...responsiveStyles, + ...setBreakpointCssVars(heights, cssBrandHeight.name) + }; + } + + return ( + /** the brand component currently contains no styling the 'pf-v6-c-brand' string will be used for the className */ + children !== undefined ? ( + + {children} + {alt} + + ) : ( + {alt} + ) + ); +}; Brand.displayName = 'Brand'; diff --git a/packages/react-core/src/components/Brand/__tests__/Brand.test.tsx b/packages/react-core/src/components/Brand/__tests__/Brand.test.tsx index 950134b6349..859e858bd25 100644 --- a/packages/react-core/src/components/Brand/__tests__/Brand.test.tsx +++ b/packages/react-core/src/components/Brand/__tests__/Brand.test.tsx @@ -1,8 +1,110 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { Brand } from '../Brand'; +import '@testing-library/jest-dom'; test('simple brand', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + render(); + expect(screen.getByAltText('brand')).toBeInTheDocument(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(); + expect(screen.getByAltText('brand')).toHaveClass('custom-class'); +}); + +test('Renders with custom class name when className prop and children are provided', () => { + render( + +
      test
      +
      + ); + expect(screen.getByText('test')?.parentElement).toHaveClass('custom-class'); +}); + +test('Renders passed children', () => { + render( + +
      test
      +
      + ); + expect(screen.getByText('test')).toBeInTheDocument(); +}); + +test('Renders as picture when children are present', () => { + render( + +
      test
      +
      + ); + expect(screen.getByText('test')?.parentElement?.tagName).toBe('PICTURE'); +}); + +test('Renders as img when no children are present', () => { + render(); + expect(screen.getByAltText('brand')?.tagName).toBe('IMG'); +}); + +test('Has correct src with passed src prop', () => { + render(); + const image = screen.getByRole('img') as HTMLImageElement; + expect(image.src).toMatch('test.png'); +}); + +test('Has correct alt text with passed alt prop', () => { + render(); + + expect(screen.getByAltText('brand')).toBeTruthy(); +}); + +test('Has correct src with passed children', () => { + render( + +
      test width
      +
      + ); + const image = screen.getByRole('img') as HTMLImageElement; + expect(image.src).toMatch('test.png'); +}); + +test('Has correct alt text with passed children', () => { + render( + +
      test width
      +
      + ); + expect(screen.getByAltText('brand')).toBeTruthy(); +}); + +test('styles get spread when there are children', () => { + render( + +
      test width
      +
      + ); + expect(screen.getByTestId('brand')).toHaveStyle(`color: blue`); +}); + +test('styles get spread when there are no children', () => { + render(); + expect(screen.getByAltText('brand no children')).toHaveStyle(`width: 30px`); +}); + +test('width styles are present when passed', () => { + render( + + ); + expect(screen.getByAltText('brand with widths')).toHaveAttribute( + 'style', + '--pf-v6-c-brand--Width: 100px; --pf-v6-c-brand--Width-on-sm: 25px; --pf-v6-c-brand--Width-on-md: 50px; --pf-v6-c-brand--Width-on-lg: 100px; --pf-v6-c-brand--Width-on-xl: 125px; --pf-v6-c-brand--Width-on-2xl: 150px;' + ); }); diff --git a/packages/react-core/src/components/Brand/__tests__/Generated/Brand.test.tsx b/packages/react-core/src/components/Brand/__tests__/Generated/Brand.test.tsx deleted file mode 100644 index 42e2e566091..00000000000 --- a/packages/react-core/src/components/Brand/__tests__/Generated/Brand.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Brand } from '../../Brand'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Brand should match snapshot (auto-generated)', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Brand/__tests__/Generated/__snapshots__/Brand.test.tsx.snap b/packages/react-core/src/components/Brand/__tests__/Generated/__snapshots__/Brand.test.tsx.snap deleted file mode 100644 index 46a2dc7db89..00000000000 --- a/packages/react-core/src/components/Brand/__tests__/Generated/__snapshots__/Brand.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Brand should match snapshot (auto-generated) 1`] = ` -string -`; diff --git a/packages/react-core/src/components/Brand/__tests__/__snapshots__/Brand.test.tsx.snap b/packages/react-core/src/components/Brand/__tests__/__snapshots__/Brand.test.tsx.snap deleted file mode 100644 index 58accdffb9d..00000000000 --- a/packages/react-core/src/components/Brand/__tests__/__snapshots__/Brand.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`simple brand 1`] = ` -brand -`; diff --git a/packages/react-core/src/components/Brand/examples/Brand.css b/packages/react-core/src/components/Brand/examples/Brand.css new file mode 100644 index 00000000000..811bb7ee236 --- /dev/null +++ b/packages/react-core/src/components/Brand/examples/Brand.css @@ -0,0 +1,12 @@ +.show-dark, +:where(.pf-v6-theme-dark) .show-light { + display: none; +} + +:where(.pf-v6-theme-dark) .show-dark { + display: revert; +} + +:where(.pf-v6-theme-dark) .show-dark .pf-m-picture { + display: inline-flex; +} \ No newline at end of file diff --git a/packages/react-core/src/components/Brand/examples/Brand.md b/packages/react-core/src/components/Brand/examples/Brand.md index a9e85b0cada..fcaa6876480 100644 --- a/packages/react-core/src/components/Brand/examples/Brand.md +++ b/packages/react-core/src/components/Brand/examples/Brand.md @@ -4,14 +4,27 @@ section: components cssPrefix: null propComponents: ['Brand'] --- -import pfLogo from './pfLogo.svg'; + +import './Brand.css'; +import pfLogo from '../../assets/PF-HorizontalLogo-Color.svg'; +import pfLogoDark from '../../assets/PF-HorizontalLogo-Reverse.svg'; +import pfLogoSm from '../../assets/PF-IconLogo-color.svg'; +import pfLogoSmDark from '../../assets/PF-IconLogo-Reverse.svg'; ## Examples + +The brand component does not have any built-in theme support. If a brand should be dynamically styled, you must manually set up the necessary logic on your own. + +These examples adjust styling when the PatternFly website is toggled between the light and dark theme. + ### Basic -```js -import React from 'react'; -import { Brand } from '@patternfly/react-core'; -import pfLogo from './examples/pfLogo.svg'; - +```ts file="./BrandBasic.tsx" +``` + +### Responsive + +Passing `` elements as children to `Brand` will change the component from an `` to a `` element. The `src` and `alt` properties should still be passed to populate the fallback `img` of the brand. + +```ts file="./BrandResponsive.tsx" ``` diff --git a/packages/react-core/src/components/Brand/examples/BrandBasic.tsx b/packages/react-core/src/components/Brand/examples/BrandBasic.tsx new file mode 100644 index 00000000000..8a4cf455bb0 --- /dev/null +++ b/packages/react-core/src/components/Brand/examples/BrandBasic.tsx @@ -0,0 +1,14 @@ +import { Brand } from '@patternfly/react-core'; +import pfLogo from '../../assets/PF-HorizontalLogo-Color.svg'; +import pfLogoDark from '../../assets/PF-HorizontalLogo-Reverse.svg'; + +export const BrandBasic: React.FunctionComponent = () => ( + <> +
      + +
      +
      + +
      + +); diff --git a/packages/react-core/src/components/Brand/examples/BrandResponsive.tsx b/packages/react-core/src/components/Brand/examples/BrandResponsive.tsx new file mode 100644 index 00000000000..fef2a7bba7a --- /dev/null +++ b/packages/react-core/src/components/Brand/examples/BrandResponsive.tsx @@ -0,0 +1,31 @@ +import { Brand } from '@patternfly/react-core'; + +import pfLogo from '../../assets/PF-HorizontalLogo-Color.svg'; +import pfLogoDark from '../../assets/PF-HorizontalLogo-Reverse.svg'; +import pfLogoSm from '../../assets/PF-IconLogo-color.svg'; +import pfLogoSmDark from '../../assets/PF-IconLogo-Reverse.svg'; + +export const BrandBasic: React.FunctionComponent = () => ( + <> +
      + + + + + + + + +
      +
      + + + + + + + + +
      + +); diff --git a/packages/react-core/src/components/Breadcrumb/Breadcrumb.tsx b/packages/react-core/src/components/Breadcrumb/Breadcrumb.tsx index ba47afb85b0..2787047cefd 100644 --- a/packages/react-core/src/components/Breadcrumb/Breadcrumb.tsx +++ b/packages/react-core/src/components/Breadcrumb/Breadcrumb.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { Children, isValidElement, cloneElement } from 'react'; import styles from '@patternfly/react-styles/css/components/Breadcrumb/breadcrumb'; import { css } from '@patternfly/react-styles'; import { useOUIAProps, OUIAProps } from '../../helpers'; @@ -10,6 +10,10 @@ export interface BreadcrumbProps extends React.HTMLProps, OUIAProps className?: string; /** Aria label added to the breadcrumb nav. */ 'aria-label'?: string; + /** Value to overwrite the randomly generated data-ouia-component-id.*/ + ouiaId?: number | string; + /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ + ouiaSafe?: boolean; } export const Breadcrumb: React.FunctionComponent = ({ @@ -23,11 +27,11 @@ export const Breadcrumb: React.FunctionComponent = ({ const ouiaProps = useOUIAProps(Breadcrumb.displayName, ouiaId, ouiaSafe); return (
      } /> + ); + + expect(screen.getByText('ICON')).toBeVisible(); + expect(screen.getByText('ICON').parentElement?.parentElement).toHaveClass(styles.modifiers.inProgress); +}); + +test('Renders as custom component when component is passed', () => { + const component = 'a'; + render(); + + expect(screen.getByText('anchor button').parentElement?.tagName).toBe('A'); }); test('aria-disabled is set to true and tabIndex to -1 if component is not a button and is disabled', () => { - const view = mount( + render( ); - expect(view).toMatchSnapshot(); + const anchor = screen.getByText('Disabled Anchor Button').parentElement; + expect(anchor).toHaveAttribute('tabindex', '-1'); + expect(anchor).toHaveAttribute('aria-disabled', 'true'); }); test('setting tab index through props', () => { - const view = mount(); - expect(view.find('button').props().tabIndex).toBe(0); + render(); + expect(screen.getByRole('button')).toHaveAttribute('tabindex', '0'); +}); + +test('Does not render aria-expanded by default', () => { + render(); + + expect(screen.getByRole('button')).not.toHaveAttribute('aria-expanded'); +}); + +test('Renders with aria-expanded when isExpanded is true', () => { + render(); + + expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'true'); +}); + +test('Renders with aria-expanded when isExpanded is false', () => { + render(); + + expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'false'); +}); + +// Remove this test when isExpanded prop in Button code is moved to after the spread props +test('Passing aria-expanded overrides isExpanded', () => { + render( + + ); + + expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'false'); +}); + +describe('Hamburger button', () => { + test('Throws console error when isHamburger is true and isExpanded is not passed', () => { + const consoleError = jest.spyOn(console, 'error').mockImplementation(); + + render( + ); + + expect(consoleError).not.toHaveBeenCalledWith( + 'Button: you must provide either visible text content or an accessible name via the aria-label or aria-labelledby properties.' + ); + }); + + // TODO: Remove isHamburger in breaking change to throw error for any button that does not have children or aria name + test('Does not throw console error when isHamburger is true and aria-label is passed', () => { + const consoleError = jest.spyOn(console, 'error').mockImplementation(); + + render(
      } />); + + expect(screen.queryByText('Custom icon')).not.toBeInTheDocument(); + }); +}); + +describe('Settings button', () => { + // TODO: Remove isSettings in breaking change to throw error for any button that does not have children or aria name + test('Throws console error when isSettings is true and neither children, aria-label nor aria-lablledby are passed', () => { + const consoleError = jest.spyOn(console, 'error').mockImplementation(); + + render(); + + expect(consoleError).not.toHaveBeenCalledWith( + 'Button: you must provide either visible text content or an accessible name via the aria-label or aria-labelledby properties.' + ); + }); + + // TODO: Remove isSettings in breaking change to throw error for any button that does not have children or aria name + test('Does not throw console error when isSettings is true and aria-label is passed', () => { + const consoleError = jest.spyOn(console, 'error').mockImplementation(); + + render(
      } />); + + expect(screen.queryByText('Custom icon')).not.toBeInTheDocument(); + }); +}); + +describe('Favorite button', () => { + // TODO: Remove isFavorite in breaking change to throw error for any button that does not have children or aria name + test('Throws console error when isFavorite is true and neither children, aria-label nor aria-lablledby are passed', () => { + const consoleError = jest.spyOn(console, 'error').mockImplementation(); + + render(); + + expect(consoleError).not.toHaveBeenCalledWith( + 'Button: you must provide either visible text content or an accessible name via the aria-label or aria-labelledby properties.' + ); + }); + + // TODO: Remove isFavorite in breaking change to throw error for any button that does not have children or aria name + test('Does not throw console error when isFavorite is true and aria-label is passed', () => { + const consoleError = jest.spyOn(console, 'error').mockImplementation(); + + render(
    } />); + expect(screen.queryByText('Icon content')).not.toBeInTheDocument(); + }); +}); + +describe('Dock variant', () => { + test(`Renders with class ${styles.modifiers.docked} when isDocked = true`, () => { + render(); + expect(screen.getByRole('button')).toHaveClass(styles.modifiers.docked); + }); + + test(`Does not render with class ${styles.modifiers.docked} when isDocked is not passed`, () => { + render(); + expect(screen.getByRole('button')).not.toHaveClass(styles.modifiers.docked); + }); + + test(`Renders with class ${styles.modifiers.textExpanded} when isTextExpanded = true and isDocked = true`, () => { + render( + + ); + expect(screen.getByRole('button')).toHaveClass(styles.modifiers.textExpanded); + }); + + test(`Does not render with class ${styles.modifiers.textExpanded} when isTextExpanded is not passed`, () => { + render(); + expect(screen.getByRole('button')).not.toHaveClass(styles.modifiers.textExpanded); + }); + + test(`Does not render with class ${styles.modifiers.textExpanded} when isTextExpanded = true but isDocked is not passed`, () => { + render(); + expect(screen.getByRole('button')).not.toHaveClass(styles.modifiers.textExpanded); + }); + + test(`Renders with both ${styles.modifiers.docked} and ${styles.modifiers.textExpanded} when both props are true`, () => { + render( + + ); + const button = screen.getByRole('button'); + expect(button).toHaveClass(styles.modifiers.docked); + expect(button).toHaveClass(styles.modifiers.textExpanded); + }); +}); + +test(`Renders basic button`, () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Button/__tests__/Generated/Button.test.tsx b/packages/react-core/src/components/Button/__tests__/Generated/Button.test.tsx deleted file mode 100644 index 0fbb6cfdbe9..00000000000 --- a/packages/react-core/src/components/Button/__tests__/Generated/Button.test.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Button } from '../../Button'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Button should match snapshot (auto-generated)', () => { - const view = shallow( - -`; - -exports[`control button 1`] = ` - - - -`; - -exports[`danger button 1`] = ` - - - -`; - -exports[`isAriaDisabled button 1`] = ` - - - -`; - -exports[`isAriaDisabled link button 1`] = ` - -`; - -exports[`isBlock 1`] = ` - - - -`; - -exports[`isDanger link 1`] = ` - - - -`; - -exports[`isDanger secondary 1`] = ` - - - -`; - -exports[`isDisabled 1`] = ` - - - -`; - -exports[`isInline 1`] = ` - - - -`; - -exports[`isLarge 1`] = ` - - - -`; - -exports[`isLoading 1`] = ` - - - -`; - -exports[`isSmall 1`] = ` - - - -`; - -exports[`link button 1`] = ` - - - -`; - -exports[`link with icon 1`] = ` - - - -`; - -exports[`plain button 1`] = ` - - - -`; - -exports[`primary button 1`] = ` - - - -`; - -exports[`secondary button 1`] = ` - - - -`; - -exports[`tertiary button 1`] = ` - - - -`; - -exports[`warning button 1`] = ` - - - +exports[`Renders basic button 1`] = ` + + + `; diff --git a/packages/react-core/src/components/Button/examples/Button.md b/packages/react-core/src/components/Button/examples/Button.md index 337b7b04914..da92cd07c5a 100644 --- a/packages/react-core/src/components/Button/examples/Button.md +++ b/packages/react-core/src/components/Button/examples/Button.md @@ -1,366 +1,187 @@ --- id: Button section: components -cssPrefix: pf-c-button -propComponents: ['Button'] +cssPrefix: pf-v6-c-button +propComponents: ['Button', 'BadgeCountObject'] ouia: true --- -import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; -import ExternalLinkSquareAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-square-alt-icon'; +import { Fragment, useState } from 'react'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; +import RhUiExternalLinkFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-external-link-fill-icon'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; -import { Link } from '@reach/router'; +import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; +import RhUiQuestionMarkCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-question-mark-circle-fill-icon'; ## Examples -### Variations +### Variant examples -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; -import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; -import ExternalLinkSquareAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-square-alt-icon'; -import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; +PatternFly supports several button styling variants to be used in different scenarios as needed. The following button variants can be assigned using the `variant` property. + +```ts file="./ButtonVariations.tsx" - - {' '} - {' '} - {' '} - {' '} - {' '} - -
    -
    - {' '} - {' '} - {' '} - -
    -
    - -
    -
    - {' '} - -
    ; ``` -### Disabled - -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; -import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - - - {' '} - {' '} - {' '} - {' '} - {' '} - -
    -
    - {' '} - {' '} - {' '} - {' '} - -
    ; +| Variant | Description | +| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Primary | Primary buttons are the most visually prominent variant. Use for the most important call to action. | +| Secondary | Secondary buttons are less visually prominant than primary buttons. Use for general actions on a page that require less emphasis than primary buttons. | +| Tertiary | Tertiary buttons are the least visually prominent variant. Use to retain a classic button format with less emphasis than primary or secondary buttons. | +| Danger | Danger buttons may be used for actions that are potentially destructive or difficult/impossible to undo. Danger is an independent variant, but all button variants may use the the `isDanger` property to apply similar styling. | +| Warning | Warning buttons may be used for actions that change an important setting or behavior, but not in a destructive or irreversible way. | +| Link | Links are labeled, but have no background or border. Use for actions that require less emphasis, actions that navigate users to another page within the same window, and/or actions that navigate to external pages in a new window. Links may be placed inline with text using the `isInline` property. | +| Plain | Plain buttons have no styling and are intended to be labeled with icons. | +| Control | Control buttons can be labeled with text or icons. Primarily intended to be paired with other controls in an [input group](/components/input-group). | +| Stateful | Stateful buttons are ideal for displaying the state of notifications. They have 3 states: `read`, `unread` and `attention`. | + +### Disabled buttons + +To indicate that an action is currently unavailable, all button variations can be disabled using the `isDisabled` property. + +```ts file="./ButtonDisabled.tsx" + ``` -### Aria disabled - -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; -import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - - - {' '} - {' '} - {' '} - {' '} - {' '} - -
    -
    - {' '} - {' '} - {' '} - {' '} - -
    ; +### Small buttons + +To fit into tight spaces, primary, secondary, tertiary, danger, and warning button variations can be made smaller using the `"sm"` value for the `size` property. + +```ts file="./ButtonSmall.tsx" + ``` -### Aria disabled button with tooltip +### Call to action (CTA) buttons + +CTA buttons and links direct users to complete an action. Primary, secondary, tertiary, and link button variants can be styled as CTAs using the `"lg"` value for the `size` property. -```js -import React from 'react'; -import { Button, Tooltip } from '@patternfly/react-core'; +```ts file="./ButtonCallToAction.tsx" - - -; ``` -### Aria disabled link as button with tooltip +### Block level buttons -```js -import React from 'react'; -import { Button, Tooltip } from '@patternfly/react-core'; +Block level buttons span the full width of the parent element and can be enabled using the `isBlock` property. + +```ts file="./ButtonBlock.tsx" + +``` + +### Progress indicators + +Progress indicators can be added to buttons to identify that an action is in progress after a click. + +```ts file="./ButtonProgress.tsx" - - -; ``` ### Links as buttons -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; - - - {' '} - {' '} - {' '} - -; +Buttons that link to another resource may take the form of primary, secondary, tertiary, or link variants. Use `component="a"` and an `href` property to designate the button's target link. + +```ts file="./ButtonLinks.tsx" + ``` ### Inline link as span -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; - -InlineLinkAsSpan = () => { - const handleKeydown = evt => { - const { keyCode } = evt; - const isEnterOrSpaceKey = keyCode === 13 || keyCode === 32; - - if (isEnterOrSpaceKey) { - evt.preventDefault(); - alert(`${keyCode === 13 ? 'Enter' : 'Space'} key default behavior stopped by onKeyDown`); - } - }; - - return ( - <> -

    - Lorem ipsum dolor sit amet, consectetur adipiscing elit. - Sed hendrerit nisi in cursus maximus. Ut malesuada nisi turpis, in condimentum velit elementum non. -

    - -
    - -

    - Note that using a span as a button does not fire the onclick event for Enter or Space keys. - Pressing the Enter or Space keys on the inline link as span above demonstrates this by triggering an alert. -

    - - ); -}; +Inline links should use `component="span"` and the `isInline` property to wrap inline with surrounding text. + +```ts file="./ButtonInlineSpanLink.tsx" + ``` -### Block level +### Custom component + +In addition to being able to pass a string to the `component` property, you can provide more fine-tuned customization by passing a callback that returns a component. -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; +```ts file="./ButtonCustomComponent.tsx" -; ``` -### Types +### Aria-disabled examples + +[Accessible Rich Internet Applications (ARIA)](https://www.w3.org/WAI/standards-guidelines/aria/) is a set of roles and attributes specified by the World Wide Web Consortium. ARIA defines ways to make web content and web applications more accessible to people with disabilities. -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; +Buttons that are aria-disabled are similar to normal disabled buttons, except they can receive focus. Every button variant can be aria-disabled using the `isAriaDisabled` property. + +Unlike normal disabled buttons, aria-disabled buttons can support tooltips. Furthermore, aria-disabled buttons can operate as links, which also support tooltips. + +```ts file="./ButtonAriaDisabled.tsx" - - -; ``` -### Small - -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; - - - {' '} - {' '} - {' '} - {' '} - -
    -
    -
    ; +### Button with count + +Buttons can display a `count` in the form of a badge to indicate some value or number by passing in the `countOptions` prop as a `BadgeCountObject` object. The `BadgeCountObject` object will handle `count`, `isRead`, and `className` props for the badge count. + +```ts file="./ButtonWithCount.tsx" + ``` -### Call to action +### Plain with no padding -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; -import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; +To display a plain/icon button inline with text, use `noPadding` prop in addition to `variant="plain"`. + +```ts file="./ButtonPlainHasNoPadding.tsx" - - {' '} - {' '} - {' '} - -
    -
    -
    ; ``` -### Progress - -```js -import React from 'react'; -import { Button } from '@patternfly/react-core'; - -ButtonProgressVariants = () => { - const [isPrimaryLoading, setIsPrimaryLoading] = React.useState(true); - const [isSecondaryLoading, setIsSecondaryLoading] = React.useState(true); - const extraPrimaryProps = {}; - if (isPrimaryLoading) { - extraPrimaryProps.spinnerAriaValueText = 'Loading'; - } - const extraSecondaryProps = {}; - if (isSecondaryLoading) { - extraSecondaryProps.spinnerAriaValueText = 'Loading'; - } - - return ( - - {' '} - -
    -
    -
    - ); -}; +### Stateful + +Stateful buttons are ideal for displaying the state of notifications. Use `variant="stateful"` alongside with the `state` property, which can have these 3 values: `read`, `unread` (used as default) and `attention` (which means unread and requires attention). + +```ts file="./ButtonStateful.tsx" + +``` + +### Circle buttons + +Pass `isCircle` to a button to modify its styling from simply rounded corners to complete circles. Circle buttons are intended for buttons that only contain an icon and adequate accessible naming. + +```ts file="./ButtonCircle.tsx" + +``` + +## Animated examples + +The following ` ``` - diff --git a/packages/react-core/src/components/Button/examples/ButtonAriaDisabled.tsx b/packages/react-core/src/components/Button/examples/ButtonAriaDisabled.tsx new file mode 100644 index 00000000000..b1be6cb6990 --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonAriaDisabled.tsx @@ -0,0 +1,27 @@ +import { Button, Flex, Tooltip } from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const ButtonAriaDisabled: React.FunctionComponent = () => ( + <> + + + + + +
    + + + + + + + + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonBlock.tsx b/packages/react-core/src/components/Button/examples/ButtonBlock.tsx new file mode 100644 index 00000000000..0481e2657eb --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonBlock.tsx @@ -0,0 +1,3 @@ +import { Button } from '@patternfly/react-core'; + +export const ButtonBlock: React.FunctionComponent = () => ; diff --git a/packages/react-core/src/components/Button/examples/ButtonCallToAction.tsx b/packages/react-core/src/components/Button/examples/ButtonCallToAction.tsx new file mode 100644 index 00000000000..c46056cbafc --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonCallToAction.tsx @@ -0,0 +1,19 @@ +import { Button, Flex } from '@patternfly/react-core'; +import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; + +export const ButtonCallToAction: React.FunctionComponent = () => ( + + + + + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonCircle.tsx b/packages/react-core/src/components/Button/examples/ButtonCircle.tsx new file mode 100644 index 00000000000..f01a19013ac --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonCircle.tsx @@ -0,0 +1,83 @@ +import { Button, Flex } from '@patternfly/react-core'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; +import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; +import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; + +interface LoadingPropsType { + spinnerAriaValueText: string; + spinnerAriaLabelledBy?: string; + spinnerAriaLabel?: string; + isLoading: boolean; +} + +export const ButtonCircle: React.FunctionComponent = () => { + const [isUploading, setIsUploading] = useState(false); + + const uploadingProps = {} as LoadingPropsType; + uploadingProps.spinnerAriaValueText = 'Loading circle variant example'; + uploadingProps.spinnerAriaLabel = 'Uploading circle variant example data'; + uploadingProps.isLoading = isUploading; + + return ( + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx b/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx new file mode 100644 index 00000000000..91abd758826 --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonDisabled.tsx @@ -0,0 +1,47 @@ +import { Button, Flex } from '@patternfly/react-core'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; +import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; + +export const ButtonDisabled: React.FunctionComponent = () => ( + <> + + + + + + + + +
    + + + + + + + Sed hendrerit nisi in cursus maximus. Ut malesuada nisi turpis, in condimentum velit elementum non. +

    + +
    + +

    + Note that using a span as a button does not fire the onclick event for Enter or Space keys. + + Pressing the Enter or Space keys on the inline link as span above demonstrates this by triggering an alert. +

    + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonLinks.tsx b/packages/react-core/src/components/Button/examples/ButtonLinks.tsx new file mode 100644 index 00000000000..1bd930e6b61 --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonLinks.tsx @@ -0,0 +1,18 @@ +import { Button, Flex } from '@patternfly/react-core'; + +export const ButtonLinks: React.FunctionComponent = () => ( + + + + + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonPlainHasNoPadding.tsx b/packages/react-core/src/components/Button/examples/ButtonPlainHasNoPadding.tsx new file mode 100644 index 00000000000..6786c7cf58e --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonPlainHasNoPadding.tsx @@ -0,0 +1,10 @@ +import { Button } from '@patternfly/react-core'; +import RhUiQuestionMarkCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-question-mark-circle-fill-icon'; + +export const ButtonPlainHasNoPadding: React.FunctionComponent = () => ( +

    + This is an example of a button + + + +
    + + + ); +}; diff --git a/packages/react-core/src/components/Button/examples/ButtonSettings.tsx b/packages/react-core/src/components/Button/examples/ButtonSettings.tsx new file mode 100644 index 00000000000..b0e95cfb4c0 --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonSettings.tsx @@ -0,0 +1,10 @@ +import { Button, Flex } from '@patternfly/react-core'; + +export const ButtonSettings: React.FunctionComponent = () => ( + + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonSmall.tsx b/packages/react-core/src/components/Button/examples/ButtonSmall.tsx new file mode 100644 index 00000000000..e031f4ffaed --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonSmall.tsx @@ -0,0 +1,21 @@ +import { Button, Flex } from '@patternfly/react-core'; + +export const ButtonSmall: React.FunctionComponent = () => ( + + + + + + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonStateful.tsx b/packages/react-core/src/components/Button/examples/ButtonStateful.tsx new file mode 100644 index 00000000000..055f0b3faad --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonStateful.tsx @@ -0,0 +1,31 @@ +import { Button, Flex } from '@patternfly/react-core'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; + +export const ButtonStateful: React.FunctionComponent = () => ( + +

    +
    + Read +
    + +
    +
    +
    + Unread +
    + +
    +
    +
    + Attention +
    + +
    +
    +); diff --git a/packages/react-core/src/components/Button/examples/ButtonTypes.tsx b/packages/react-core/src/components/Button/examples/ButtonTypes.tsx new file mode 100644 index 00000000000..c07934d7918 --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonTypes.tsx @@ -0,0 +1,9 @@ +import { Button, Flex } from '@patternfly/react-core'; + +export const ButtonTypes: React.FunctionComponent = () => ( + + + + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonVariations.tsx b/packages/react-core/src/components/Button/examples/ButtonVariations.tsx new file mode 100644 index 00000000000..f7ec34082ba --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonVariations.tsx @@ -0,0 +1,64 @@ +import { Button, Flex } from '@patternfly/react-core'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; +import RhUiExternalLinkFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-external-link-fill-icon'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; +import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; + +export const ButtonVariations: React.FunctionComponent = () => ( + <> + + + + + + + + +
    + + + + + + + + + + + +); diff --git a/packages/react-core/src/components/Button/examples/ButtonWithCount.tsx b/packages/react-core/src/components/Button/examples/ButtonWithCount.tsx new file mode 100644 index 00000000000..e56340ffb5f --- /dev/null +++ b/packages/react-core/src/components/Button/examples/ButtonWithCount.tsx @@ -0,0 +1,95 @@ +import { BadgeCountObject, Button, Flex } from '@patternfly/react-core'; + +export const ButtonWithCount: React.FunctionComponent = () => { + const badgeCountObjectNotRead: BadgeCountObject = { + isRead: false, + count: 7, + className: 'custom-badge-unread' + }; + + const badgeCountObjectRead: BadgeCountObject = { + isRead: true, + count: 10, + className: 'custom-badge-read' + }; + + return ( + <> +
    Unread:
    + + + + + + + +
    +
    Unread disabled:
    + + + + + + + +
    +
    Read:
    + + + + + + + +
    +
    Read disabled:
    + + + + + + + + + ); +}; diff --git a/packages/react-core/src/components/Button/hamburgerIcon.tsx b/packages/react-core/src/components/Button/hamburgerIcon.tsx new file mode 100644 index 00000000000..70770e054b8 --- /dev/null +++ b/packages/react-core/src/components/Button/hamburgerIcon.tsx @@ -0,0 +1,13 @@ +import styles from '@patternfly/react-styles/css/components/Button/button'; +import { css } from '@patternfly/react-styles'; + +// Because this is such a specific icon that requires being wrapped in a pf-v[current version]-c-button element, +// we don't want to export this to consumers nor include it in the react-icons package as a custom icon. +export const hamburgerIcon = ( + + + + + + +); diff --git a/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx b/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx index 900d12480c9..c49e32bda61 100644 --- a/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx +++ b/packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx @@ -1,12 +1,15 @@ -import React, { useEffect } from 'react'; -import { TextInput } from '../TextInput/TextInput'; -import { Button } from '../Button/Button'; -import { Select, SelectOption } from '../Select'; -import ArrowLeftIcon from '@patternfly/react-icons/dist/esm/icons/arrow-left-icon'; -import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import { TextInput } from '../TextInput'; +import { Button } from '../Button'; +import { Select, SelectList, SelectOption } from '../Select'; +import { MenuToggle, MenuToggleElement } from '../MenuToggle'; +import { InputGroup, InputGroupItem } from '../InputGroup'; +import RhMicronsCaretLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-left-icon'; +import RhMicronsCaretRightIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-right-icon'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/CalendarMonth/calendar-month'; -import { getUniqueId } from '../../helpers/util'; +import { useSSRSafeId } from '../../helpers'; +import { isValidDate } from '../../helpers/datetimeUtils'; export enum Weekday { Sunday = 0, @@ -18,65 +21,103 @@ export enum Weekday { Saturday } +export interface CalendarMonthInlineProps { + /** Component wrapping the calendar month when used inline. Recommended to be 'article'. */ + component?: keyof React.JSX.IntrinsicElements; + /** Title of the calendar rendered above the inline calendar month. Recommended to be a 'title' component. */ + title?: React.ReactNode; + /** Id of the accessible label of the calendar month. Recommended to map to the title. */ + ariaLabelledby?: string; +} + +/** Additional properties that extend from and can be passed to the main component. These + * properties allow customizing the calendar formatting and aria-labels. + */ + export interface CalendarFormat { - /** How to format months in Select */ - monthFormat?: (date: Date) => React.ReactNode; - /** How to format week days in header */ - weekdayFormat?: (date: Date) => React.ReactNode; - /** How to format days in header for screen readers */ - longWeekdayFormat?: (date: Date) => React.ReactNode; - /** How to format days in buttons in table cells */ + /** Accessible label for the date cells. */ + cellAriaLabel?: (date: Date) => string; + /** How to format days in buttons in table cells. */ dayFormat?: (date: Date) => React.ReactNode; - /** If using the default formatters which locale to use. Undefined defaults to current locale. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation */ + /** If using the default formatters which locale to use. Undefined defaults to current locale. + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation + */ locale?: string; - /** Day of week that starts the week. 0 is Sunday, 6 is Saturday. */ - weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | Weekday; - /** Which date to start range styles from */ - rangeStart?: Date; - /** Aria-label for the previous month button */ + /** How to format days in header for screen readers. */ + longWeekdayFormat?: (date: Date) => React.ReactNode; + /** How to format months in month select. */ + monthFormat?: (date: Date) => React.ReactNode; + /** Accessible label for the previous month button. */ prevMonthAriaLabel?: string; - /** Aria-label for the next month button */ + /** Accessible label for the next month button. */ nextMonthAriaLabel?: string; - /** Aria-label for the year input */ + /** Which date to start range styles from. */ + rangeStart?: Date; + /** How to format week days in header. */ + weekdayFormat?: (date: Date) => React.ReactNode; + /** Day of week that starts the week. 0 is Sunday, 6 is Saturday. */ + weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | Weekday; + /** Accessible label for the year input. */ yearInputAriaLabel?: string; - /** Aria-label for the date cells */ - cellAriaLabel?: (date: Date) => string; + /** Props used to ensure accessibility when displaying the calendar month inline. */ + inlineProps?: CalendarMonthInlineProps; } export interface CalendarProps extends CalendarFormat, Omit, 'onChange'> { - /** Month/year to base other dates around */ - date: Date; - /** Callback when date is selected */ - onChange?: (date: Date) => void; - /** Functions that returns if a date is valid and selectable */ - validators?: ((date: Date) => boolean)[]; - /** Classname to add to outer div */ + /** Additional classes to add to the outer div of the calendar month. */ className?: string; - /** @hide Internal prop to allow pressing escape in select menu to not close popover */ + /** Month/year to base other dates around. */ + date?: Date; + /** Flag to set browser focus on the passed date. **/ + isDateFocused?: boolean; + /** Callback when date is selected. */ + onChange?: (event: React.MouseEvent, date: Date) => void; + /** Callback when month or year is changed. */ + onMonthChange?: ( + event?: React.MouseEvent | React.ChangeEvent | React.FormEvent, + newDate?: Date + ) => void; + /** @hide Internal prop to allow pressing escape in select menu to not close popover. */ onSelectToggle?: (open: boolean) => void; + /** Functions that returns if a date is valid and selectable. */ + validators?: ((date: Date) => boolean)[]; + /** The container to append the month select menu to. Defaults to 'inline'. + * If your menu is being cut off you can append it to an element higher up the DOM tree. + * Some examples: + * monthAppendTo={() => document.body}; + * monthAppendTo={document.getElementById('target')} + */ + monthAppendTo?: HTMLElement | ((ref?: HTMLElement) => HTMLElement) | 'inline'; } -// Must be numeric given current header design -const yearFormat = (date: Date) => date.getFullYear(); - const buildCalendar = (year: number, month: number, weekStart: number, validators: ((date: Date) => boolean)[]) => { - const selectedDate = new Date(year, month); - const firstDayOfWeek = new Date(selectedDate); + const defaultDate = new Date(year, month); + + const firstDayOfWeek = new Date(defaultDate); firstDayOfWeek.setDate(firstDayOfWeek.getDate() - firstDayOfWeek.getDay() + weekStart); - // We will always show 6 weeks like google calendar + + // We will show a maximum of 6 weeks like Google calendar // Assume we just want the numbers for now... const calendarWeeks = []; + + if (firstDayOfWeek.getMonth() === defaultDate.getMonth() && firstDayOfWeek.getDate() !== 1) { + firstDayOfWeek.setDate(firstDayOfWeek.getDate() - 7); + } for (let i = 0; i < 6; i++) { const week = []; + for (let j = 0; j < 7; j++) { const date = new Date(firstDayOfWeek); week.push({ date, - isValid: validators.every(validator => validator(date)) + isValid: validators.every((validator) => validator(date)) }); firstDayOfWeek.setDate(firstDayOfWeek.getDate() + 1); } calendarWeeks.push(week); + if (firstDayOfWeek.getMonth() !== defaultDate.getMonth()) { + break; + } } return calendarWeeks; @@ -85,63 +126,83 @@ const buildCalendar = (year: number, month: number, weekStart: number, validator const isSameDate = (d1: Date, d2: Date) => d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate(); -export const isValidDate = (date: Date) => Boolean(date && !isNaN(date as any)); - const today = new Date(); +/** The main calendar month component. */ + export const CalendarMonth = ({ - date: dateProp = today, + date: dateProp, locale = undefined, - monthFormat = date => date.toLocaleDateString(locale, { month: 'long' }), - weekdayFormat = date => date.toLocaleDateString(locale, { weekday: 'narrow' }), - longWeekdayFormat = date => date.toLocaleDateString(locale, { weekday: 'long' }), - dayFormat = date => date.getDate(), + monthFormat = (date) => date.toLocaleDateString(locale, { month: 'long' }), + weekdayFormat = (date) => date.toLocaleDateString(locale, { weekday: 'narrow' }), + longWeekdayFormat = (date) => date.toLocaleDateString(locale, { weekday: 'long' }), + dayFormat = (date) => date.getDate(), weekStart = 0, // Use the American Sunday as a default onChange = () => {}, validators = [() => true], className, onSelectToggle = () => {}, + onMonthChange = () => {}, rangeStart, prevMonthAriaLabel = 'Previous month', nextMonthAriaLabel = 'Next month', yearInputAriaLabel = 'Select year', cellAriaLabel, + isDateFocused = false, + inlineProps, + monthAppendTo = 'inline', ...props }: CalendarProps) => { - const longMonths = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map(monthNum => new Date(1990, monthNum)).map(monthFormat); - const [isSelectOpen, setIsSelectOpen] = React.useState(false); - // eslint-disable-next-line prefer-const - let [focusedDate, setFocusedDate] = React.useState(new Date(dateProp)); - if (!isValidDate(focusedDate)) { - focusedDate = today; - } - const [hoveredDate, setHoveredDate] = React.useState(new Date(focusedDate)); - const focusRef = React.useRef(); - const [hiddenMonthId] = React.useState(getUniqueId('hidden-month-span')); - const [shouldFocus, setShouldFocus] = React.useState(true); + const longMonths = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] + .map((monthNum) => new Date(1990, monthNum)) + .map(monthFormat); + const [isSelectOpen, setIsSelectOpen] = useState(false); + + const getInitialDate = () => { + if (isValidDate(dateProp)) { + return dateProp; + } + if (isValidDate(rangeStart)) { + return rangeStart; + } + return today; + }; + const initialDate = getInitialDate(); + const [focusedDate, setFocusedDate] = useState(initialDate); + + // Must be numeric given current header design + const yearFormat = (date: Date) => date.getFullYear(); + // + const yearFormatted = yearFormat(focusedDate); + const [yearInput, setYearInput] = useState(yearFormatted.toString()); - const isValidated = (date: Date) => validators.every(validator => validator(date)); + const [hoveredDate, setHoveredDate] = useState(undefined); + const focusRef = useRef(undefined); + const hiddenMonthId = useSSRSafeId('hidden-month-span'); + const [shouldFocus, setShouldFocus] = useState(false); + + const isValidated = (date: Date) => validators.every((validator) => validator(date)); const focusedDateValidated = isValidated(focusedDate); useEffect(() => { - if (!(isValidDate(dateProp) && isSameDate(focusedDate, dateProp))) { + if (isValidDate(dateProp) && !isSameDate(focusedDate, dateProp)) { setFocusedDate(dateProp); + } else if (!dateProp) { + setFocusedDate(today); } }, [dateProp]); + useEffect(() => { - // When using header controls don't move focus - if (shouldFocus) { - if (focusRef.current && focusedDateValidated) { - focusRef.current.focus(); - } - } else { - setShouldFocus(true); + // Calendar month should not be focused on page load + if ((shouldFocus || isDateFocused) && focusedDateValidated && focusRef.current) { + focusRef.current.focus(); } - }, [focusedDate]); + }, [focusedDate, isDateFocused, focusedDateValidated, focusRef]); - const onMonthClick = (newDate: Date) => { + const onMonthClick = (ev: React.MouseEvent, newDate: Date) => { setFocusedDate(newDate); - setHoveredDate(newDate); setShouldFocus(false); + onMonthChange(ev, newDate); + setYearInput(yearFormat(newDate).toString()); }; const onKeyDown = (ev: React.KeyboardEvent) => { @@ -158,27 +219,65 @@ export const CalendarMonth = ({ if (newDate.getTime() !== focusedDate.getTime() && isValidated(newDate)) { ev.preventDefault(); setFocusedDate(newDate); - setHoveredDate(newDate); setShouldFocus(true); } }; + const changeYear = (newYear: number) => changeMonth(focusedDate.getMonth(), newYear); + + const changeMonth = (newMonth: number, newYear?: number) => + new Date(newYear ?? focusedDate.getFullYear(), newMonth, 1); + + const MIN_YEAR = 1900; + const MAX_YEAR = 2100; + + const handleYearInputChange = (event: React.FormEvent, yearStr: string) => { + if (!/^\d{0,4}$/.test(yearStr)) { + return; + } + + setYearInput(yearStr); + + if (yearStr.length === 4) { + const yearNum = Number(yearStr); + + if (yearNum >= MIN_YEAR && yearNum <= MAX_YEAR) { + const newDate = changeYear(yearNum); + setFocusedDate(newDate); + setShouldFocus(false); + + // We need to manually focus the year input in FireFox when the scroll buttons are clicked, as FireFox doesn't place focus automatically + (event.target as HTMLElement).focus(); + onMonthChange(event, newDate); + } else { + setYearInput(yearFormatted.toString()); + } + } + }; + const addMonth = (toAdd: -1 | 1) => { - const newDate = new Date(focusedDate); - newDate.setMonth(newDate.getMonth() + toAdd); - return newDate; + let newMonth = focusedDate.getMonth() + toAdd; + let newYear = focusedDate.getFullYear(); + + if (newMonth === -1) { + newMonth = 11; + newYear--; + } else if (newMonth === 12) { + newMonth = 0; + newYear++; + } + + return changeMonth(newMonth, newYear); }; const prevMonth = addMonth(-1); const nextMonth = addMonth(1); const focusedYear = focusedDate.getFullYear(); const focusedMonth = focusedDate.getMonth(); - const calendar = React.useMemo(() => buildCalendar(focusedYear, focusedMonth, weekStart, validators), [ - focusedYear, - focusedMonth, - weekStart, - validators - ]); + const calendar = useMemo( + () => buildCalendar(focusedYear, focusedMonth, weekStart, validators), + [focusedYear, focusedMonth, weekStart, validators] + ); if (!focusedDateValidated) { const toFocus = calendar .reduce((acc, cur) => [...acc, ...cur], []) @@ -188,82 +287,92 @@ export const CalendarMonth = ({ .map(({ date }) => date)[0]; if (toFocus) { setFocusedDate(toFocus); - setHoveredDate(toFocus); } } - const isHoveredDateValid = isValidated(hoveredDate); + const isHoveredDateValid = hoveredDate && isValidated(hoveredDate); const monthFormatted = monthFormat(focusedDate); - const yearFormatted = yearFormat(focusedDate); - return ( + + const calendarToRender = (
    -
    - -
    -
    - - -
    -
    - { - const newDate = new Date(focusedDate); - newDate.setFullYear(+year); - setFocusedDate(newDate); - setHoveredDate(newDate); - setShouldFocus(false); - }} +
    +
    -
    - + + +
    + + +
    +
    + +
    + +
    +
    +
    +
    +
    - +
    setHoveredDate(undefined)}> {calendar[0].map(({ date }, index) => ( ))} @@ -278,17 +387,24 @@ export const CalendarMonth = ({ const isSelected = isValidDate(dateProp) && isSameDate(date, dateProp); const isFocused = isSameDate(date, focusedDate); const isAdjacentMonth = date.getMonth() !== focusedDate.getMonth(); + const isRangeStart = isValidDate(rangeStart) && isSameDate(date, rangeStart); let isInRange = false; - let isRangeStart = false; let isRangeEnd = false; - if (isValidDate(rangeStart) && isHoveredDateValid) { - if (hoveredDate > rangeStart || isSameDate(hoveredDate, rangeStart)) { - isInRange = date > rangeStart && date < hoveredDate; - isRangeStart = isSameDate(date, rangeStart); - isRangeEnd = isSameDate(date, hoveredDate); + if (isValidDate(rangeStart)) { + let rangeEndDate: Date; + + if (isValidDate(dateProp)) { + rangeEndDate = dateProp; + } + if (isHoveredDateValid && (!isValidDate(dateProp) || hoveredDate > dateProp)) { + rangeEndDate = hoveredDate; } - // Don't handle focused dates before start dates for now. - // Core would likely need new styles + + if (rangeEndDate) { + isInRange = date >= rangeStart && date <= rangeEndDate; + isRangeEnd = isSameDate(date, rangeEndDate); + } + // Core would likely need new styles for "is selected but disabled" } return ( @@ -299,8 +415,8 @@ export const CalendarMonth = ({ isAdjacentMonth && styles.modifiers.adjacentMonth, isToday && styles.modifiers.current, (isSelected || isRangeStart) && styles.modifiers.selected, - !isValid && styles.modifiers.disabled, - (isInRange || isRangeStart || isRangeEnd) && styles.modifiers.inRange, + !isValid && !(isInRange || isRangeStart || isRangeEnd || isSelected) && styles.modifiers.disabled, + isInRange && styles.modifiers.inRange, isRangeStart && styles.modifiers.startRange, isRangeEnd && styles.modifiers.endRange )} @@ -312,12 +428,14 @@ export const CalendarMonth = ({ !isValid && styles.modifiers.disabled )} type="button" - onClick={() => onChange(date)} + onClick={(event) => onChange(event, date)} onMouseOver={() => setHoveredDate(date)} tabIndex={isFocused ? 0 : -1} disabled={!isValid} aria-label={ - cellAriaLabel ? cellAriaLabel(date) : `${dayFormatted} ${monthFormatted} ${yearFormatted}` + cellAriaLabel + ? cellAriaLabel(date) + : `${dayFormat(date)} ${monthFormat(date)} ${yearFormat(date)}` } {...(isFocused && { ref: focusRef })} > @@ -332,4 +450,16 @@ export const CalendarMonth = ({
    - {longWeekdayFormat(date)} + {longWeekdayFormat(date)} {weekdayFormat(date)}
    ); + + if (inlineProps !== undefined) { + const Component = (inlineProps.component ? inlineProps.component : 'article') as any; + return ( + + {inlineProps.title} + {calendarToRender} + + ); + } + return calendarToRender; }; +CalendarMonth.displayName = 'CalendarMonth'; diff --git a/packages/react-core/src/components/CalendarMonth/__tests__/CalendarMonth.test.tsx b/packages/react-core/src/components/CalendarMonth/__tests__/CalendarMonth.test.tsx new file mode 100644 index 00000000000..28afa2b5c62 --- /dev/null +++ b/packages/react-core/src/components/CalendarMonth/__tests__/CalendarMonth.test.tsx @@ -0,0 +1,66 @@ +import { render, screen } from '@testing-library/react'; + +import { CalendarMonth } from '../CalendarMonth'; + +test('Renders the first date in a month when a custom weekStart is passed', () => { + // custom aria label generation function because of bug with default aria label generation + // can be removed once the bug is fixed + const formatAria = (date: Date) => + `${date.getDate()} ${date.toLocaleDateString(undefined, { month: 'long' })} ${date.getFullYear()}`; + + render(); + + const firstDate = screen.getByRole('button', { name: '1 January 2023' }); + expect(firstDate).toBeVisible(); +}); + +test('Renders the last date in a month when a custom weekStart is passed', () => { + // custom aria label generation function because of bug with default aria labels + // can be removed once the bug is fixed + const formatAria = (date: Date) => + `${date.getDate()} ${date.toLocaleDateString(undefined, { month: 'long' })} ${date.getFullYear()}`; + + render(); + + const lastDate = screen.getByRole('button', { name: '31 January 2023' }); + expect(lastDate).toBeVisible(); +}); + +test('Previous month dates have correct month in aria label', () => { + render(); + + const previousMonthDate = screen.getByRole('button', { name: '31 May 2024' }); + expect(previousMonthDate).toBeVisible(); +}); + +test('Next month dates have correct month in aria label', () => { + render(); + + const nextMonthDate = screen.getByRole('button', { name: '1 August 2024' }); + expect(nextMonthDate).toBeVisible(); +}); + +test('Previous year dates have correct year in aria label', () => { + render(); + + const previousYearDate = screen.getByRole('button', { name: '31 December 2023' }); + expect(previousYearDate).toBeVisible(); +}); + +test('Next year dates have correct year in aria label', () => { + render(); + + const nextYearDate = screen.getByRole('button', { name: '1 January 2025' }); + expect(nextYearDate).toBeVisible(); +}); + +test('InlineProps render correct wrapper component and attributes', () => { + render( + Title
    , ariaLabelledby: 'hi' }} /> + ); + + const article = screen.getByRole('article'); + expect(article).toHaveAttribute('aria-labelledby', 'hi'); + const title = screen.getByText('Title'); + expect(title).toBeVisible(); +}); diff --git a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md index ef0b44817aa..ab5a6a3005e 100644 --- a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md +++ b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonth.md @@ -1,35 +1,26 @@ --- id: Calendar month section: components -cssPrefix: pf-c-calendar-month -propComponents: ['CalendarMonth', 'CalendarFormat'] -beta: true +subsection: date-and-time +cssPrefix: pf-v6-c-calendar-month +propComponents: ['CalendarMonth', 'CalendarFormat', 'CalendarMonthInlineProps'] --- +import { useState } from 'react'; ## Examples -### Default -```js -import React from 'react'; -import { CalendarMonth } from '@patternfly/react-core'; +### Selectable date - -``` +```ts file="./CalendarMonthSelectableDate.tsx" -### Selectable date -```js -import React from 'react'; -import { CalendarMonth } from '@patternfly/react-core'; - -SelectableCalendarMonth = () => { - const [date, setDate] = React.useState(new Date(2020, 10, 24)); - - return ( - -
    Selected date: {date.toString()}
    - -
    - ); -} ``` +### Date range + +In this example, there are 2 dates selected: a range start date (via the `rangeStart` prop) and a range end date (via the `date` prop). Additionally, any dates prior to the range start date are disabled by passing in an array of functions to the `validators` prop. In this case a single function is passed in, which checks whether a date is greater than or equal to the range start date. + +For this example, these dates are static and cannot be updated. For an interactive demo, see our [Date picker demos](/components/date-and-time/date-picker/react-demos). + +```ts file="./CalendarMonthDateRange.tsx" + +``` diff --git a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthDateRange.tsx b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthDateRange.tsx new file mode 100644 index 00000000000..a2654d98e11 --- /dev/null +++ b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthDateRange.tsx @@ -0,0 +1,26 @@ +import { CalendarMonth, Title, CalendarMonthInlineProps } from '@patternfly/react-core'; + +export const CalendarMonthDateRange: React.FunctionComponent = () => { + const startDate = new Date(2020, 10, 11); + const endDate = new Date(2020, 10, 24); + const disablePreStartDates = (date: Date) => date >= startDate; + + const inlineProps: CalendarMonthInlineProps = { + component: 'article', + title: ( + + Calendar month displaying a range + + ), + ariaLabelledby: 'display-range' + }; + + return ( + + ); +}; diff --git a/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthSelectableDate.tsx b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthSelectableDate.tsx new file mode 100644 index 00000000000..876f2b3dda0 --- /dev/null +++ b/packages/react-core/src/components/CalendarMonth/examples/CalendarMonthSelectableDate.tsx @@ -0,0 +1,36 @@ +import { useState } from 'react'; +import { CalendarMonth, Title, CalendarMonthInlineProps } from '@patternfly/react-core'; + +export const CalendarMonthSelectableDate: React.FunctionComponent = () => { + const [date, setDate] = useState(new Date(2020, 10, 24)); + + const onMonthChange = ( + _event: React.MouseEvent | React.ChangeEvent | React.FormEvent | undefined, + newDate: Date + ) => { + // eslint-disable-next-line no-console + console.log(`updated month: ${newDate.getMonth()}, updated year: ${newDate.getFullYear()}`); + }; + + const inlineProps: CalendarMonthInlineProps = { + component: 'article', + title: ( + + Select your favorite date + + ), + ariaLabelledby: 'favorite-date' + }; + + return ( + <> + , date: Date) => setDate(date)} + onMonthChange={onMonthChange} + inlineProps={inlineProps} + /> +
    Selected date: {date.toString()}
    + + ); +}; diff --git a/packages/react-core/src/components/Card/Card.tsx b/packages/react-core/src/components/Card/Card.tsx index ac22e2c151b..b3e0ad1f024 100644 --- a/packages/react-core/src/components/Card/Card.tsx +++ b/packages/react-core/src/components/Card/Card.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { createContext, forwardRef } from 'react'; import styles from '@patternfly/react-styles/css/components/Card/card'; import { css } from '@patternfly/react-styles'; import { useOUIAProps, OUIAProps } from '../../helpers'; @@ -10,67 +10,89 @@ export interface CardProps extends React.HTMLProps, OUIAProps { id?: string; /** Additional classes added to the Card */ className?: string; - /** Sets the base component to render. defaults to article */ - component?: keyof JSX.IntrinsicElements; - /** @deprecated to make a card hoverable, use isSelectable or isSelectableRaised. */ - isHoverable?: boolean; + /** Sets the base component to render. defaults to div */ + component?: keyof React.JSX.IntrinsicElements; /** Modifies the card to include compact styling. Should not be used with isLarge. */ isCompact?: boolean; - /** Modifies the card to include selectable styling */ + /** Flag indicating that the card is selectable. */ isSelectable?: boolean; - /** @beta Specifies the card is selectable, and applies the new raised styling on hover and select */ - isSelectableRaised?: boolean; - /** Modifies the card to include selected styling */ + /** Flag indicating that the card is clickable and contains some action that triggers on click. */ + isClickable?: boolean; + /** Flag indicating whether a card that is either selectable only or both clickable and selectable is + * currently selected and has selected styling. + */ isSelected?: boolean; - /** @beta Modifies a raised selectable card to have disabled styling */ - isDisabledRaised?: boolean; - /** Modifies the card to include flat styling */ - isFlat?: boolean; - /** Modifies the card to include rounded styling */ - isRounded?: boolean; + /** Flag indicating whether a card that is either only clickable or that is both clickable and selectable + * is currently clicked and has clicked styling. + */ + isClicked?: boolean; + /** Flag indicating that a clickable or selectable card is disabled. */ + isDisabled?: boolean; /** Modifies the card to be large. Should not be used with isCompact. */ isLarge?: boolean; /** Cause component to consume the available height of its container */ isFullHeight?: boolean; /** Modifies the card to include plain styling; this removes border and background */ isPlain?: boolean; + /** Modifies the card to include glass styling when glass theme is enabled */ + isGlass?: boolean; /** Flag indicating if a card is expanded. Modifies the card to be expandable. */ isExpanded?: boolean; + /** Card background color variant */ + variant?: 'default' | 'secondary'; + /** Value to overwrite the randomly generated data-ouia-component-id.*/ + ouiaId?: number | string; + /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ + ouiaSafe?: boolean; + /** @hide Forwarded ref */ + innerRef?: React.Ref; } interface CardContextProps { cardId: string; isExpanded: boolean; + isClickable: boolean; + isSelectable: boolean; + isSelected: boolean; + isClicked: boolean; + isDisabled: boolean; } -export const CardContext = React.createContext>({ +export const CardContext = createContext>({ cardId: '', - isExpanded: false + isExpanded: false, + isClickable: false, + isSelectable: false, + isSelected: false, + isClicked: false, + isDisabled: false }); -export const Card: React.FunctionComponent = ({ - children = null, +const CardBase: React.FunctionComponent = ({ + children, id = '', - className = '', - component = 'article', - isHoverable = false, + className, + component = 'div', isCompact = false, isSelectable = false, - isSelectableRaised = false, + isClickable = false, + isDisabled = false, isSelected = false, - isDisabledRaised = false, - isFlat = false, + isClicked = false, isExpanded = false, - isRounded = false, isLarge = false, isFullHeight = false, isPlain = false, + isGlass = false, + variant = 'default', ouiaId, ouiaSafe = true, + innerRef, ...props }: CardProps) => { const Component = component as any; const ouiaProps = useOUIAProps(Card.displayName, ouiaId, ouiaSafe); + if (isCompact && isLarge) { // eslint-disable-next-line no-console console.warn('Card: Cannot use isCompact with isLarge. Defaulting to isCompact'); @@ -78,15 +100,22 @@ export const Card: React.FunctionComponent = ({ } const getSelectableModifiers = () => { - if (isDisabledRaised) { - return css(styles.modifiers.nonSelectableRaised); - } - if (isSelectableRaised) { - return css(styles.modifiers.selectableRaised, isSelected && styles.modifiers.selectedRaised); + if (isSelectable && isClickable) { + return css( + styles.modifiers.selectable, + styles.modifiers.clickable, + (isSelected || isClicked) && styles.modifiers.current + ); } - if (isSelectable || isHoverable) { + + if (isSelectable) { return css(styles.modifiers.selectable, isSelected && styles.modifiers.selected); } + + if (isClickable) { + return css(styles.modifiers.clickable, isClicked && styles.modifiers.current); + } + return ''; }; @@ -94,24 +123,30 @@ export const Card: React.FunctionComponent = ({ @@ -120,4 +155,7 @@ export const Card: React.FunctionComponent = ({ ); }; + +export const Card = forwardRef((props: CardProps, ref: React.Ref) => ); + Card.displayName = 'Card'; diff --git a/packages/react-core/src/components/Card/CardActions.tsx b/packages/react-core/src/components/Card/CardActions.tsx index c0443350d77..5732439ea0d 100644 --- a/packages/react-core/src/components/Card/CardActions.tsx +++ b/packages/react-core/src/components/Card/CardActions.tsx @@ -1,19 +1,18 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Card/card'; export interface CardActionsProps extends React.HTMLProps { - /** Content rendered inside the Card Action */ + /** Content rendered inside the card action */ children?: React.ReactNode; - /** Additional classes added to the Action */ + /** Additional classes added to the action */ className?: string; /** Flag indicating that the actions have no offset */ hasNoOffset?: boolean; } export const CardActions: React.FunctionComponent = ({ - children = null, - className = '', + children, + className, hasNoOffset = false, ...props }: CardActionsProps) => ( diff --git a/packages/react-core/src/components/Card/CardBody.tsx b/packages/react-core/src/components/Card/CardBody.tsx index c407e0b9587..da14d0fe16c 100644 --- a/packages/react-core/src/components/Card/CardBody.tsx +++ b/packages/react-core/src/components/Card/CardBody.tsx @@ -1,7 +1,8 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Card/card'; import { css } from '@patternfly/react-styles'; +import type { JSX } from 'react'; + export interface CardBodyProps extends React.HTMLProps { /** Content rendered inside the Card Body */ children?: React.ReactNode; @@ -14,8 +15,8 @@ export interface CardBodyProps extends React.HTMLProps { } export const CardBody: React.FunctionComponent = ({ - children = null, - className = '', + children, + className, component = 'div', isFilled = true, ...props diff --git a/packages/react-core/src/components/Card/CardExpandableContent.tsx b/packages/react-core/src/components/Card/CardExpandableContent.tsx index 571d7128475..9def7cebfba 100644 --- a/packages/react-core/src/components/Card/CardExpandableContent.tsx +++ b/packages/react-core/src/components/Card/CardExpandableContent.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Card/card'; import { css } from '@patternfly/react-styles'; import { CardContext } from './Card'; @@ -11,8 +10,8 @@ export interface CardExpandableContentProps extends React.HTMLProps = ({ - children = null, - className = '', + children, + className, ...props }: CardExpandableContentProps) => ( diff --git a/packages/react-core/src/components/Card/CardFooter.tsx b/packages/react-core/src/components/Card/CardFooter.tsx index b9aefaffe84..09078bd8931 100644 --- a/packages/react-core/src/components/Card/CardFooter.tsx +++ b/packages/react-core/src/components/Card/CardFooter.tsx @@ -1,7 +1,8 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Card/card'; import { css } from '@patternfly/react-styles'; +import type { JSX } from 'react'; + export interface CardFooterProps extends React.HTMLProps { /** Content rendered inside the Card Footer */ children?: React.ReactNode; @@ -12,8 +13,8 @@ export interface CardFooterProps extends React.HTMLProps { } export const CardFooter: React.FunctionComponent = ({ - children = null, - className = '', + children, + className, component = 'div', ...props }: CardFooterProps) => { diff --git a/packages/react-core/src/components/Card/CardHeadMain.tsx b/packages/react-core/src/components/Card/CardHeadMain.tsx deleted file mode 100644 index 92925d0ff2b..00000000000 --- a/packages/react-core/src/components/Card/CardHeadMain.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; - -export interface CardHeadMainProps extends React.HTMLProps { - /** Content rendered inside the Card Head Main */ - children?: React.ReactNode; - /** Additional classes added to the Card Head Main */ - className?: string; -} - -export const CardHeadMain: React.FunctionComponent = ({ - children = null, - className = '', - ...props -}: CardHeadMainProps) => ( -
    - {children} -
    -); -CardHeadMain.displayName = 'CardHeadMain'; diff --git a/packages/react-core/src/components/Card/CardHeader.tsx b/packages/react-core/src/components/Card/CardHeader.tsx index 5d4bcbf0c8c..dc0cc411511 100644 --- a/packages/react-core/src/components/Card/CardHeader.tsx +++ b/packages/react-core/src/components/Card/CardHeader.tsx @@ -1,15 +1,72 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Card/card'; import { CardContext } from './Card'; +import { CardHeaderMain } from './CardHeaderMain'; +import { CardActions } from './CardActions'; +import { CardSelectableActions } from './CardSelectableActions'; import { Button } from '../Button'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon'; +import { Radio } from '../Radio'; +import { Checkbox } from '../Checkbox'; +import { useSSRSafeId } from '../../helpers'; + +export interface CardHeaderActionsObject { + /** Actions of the card header */ + actions: React.ReactNode; + /** Flag indicating that the actions have no offset */ + hasNoOffset?: boolean; + /** Additional classes added to the actions wrapper */ + className?: string; +} + +export interface CardHeaderSelectableActionsObject { + /** Determines the type of input to be used for a selectable card. */ + variant?: 'single' | 'multiple'; + /** Flag indicating that the actions have no offset */ + hasNoOffset?: boolean; + /** Additional classes added to the selectable actions wrapper */ + className?: string; + /** Custom ID passed to the selectable card's input or a clickable-only card's button/anchor. + * If omitted, a random unique ID will be assigned to a selectable card's input. */ + selectableActionId?: string; + /** Adds an accessible name to the input of a selectable card or clickable button/anchor of a clickable-only card. + * This or selectableActionAriaLabelledby is required for clickable-only cards. + */ + selectableActionAriaLabel?: string; + /** A single or list of space-delimited ID's that provide an accessible name to the input of a selectable card + * or clickable button/anchor of a clickable-only card. This or selectableActionAriaLabelledby is required + * for clickable-only cards. + */ + selectableActionAriaLabelledby?: string; + /** Callback for when a selectable card input changes */ + onChange?: (event: React.FormEvent, checked: boolean) => void; + /** Action to call when a clickable-only card is clicked. This cannot be combined with the to prop. */ + onClickAction?: (event: React.MouseEvent) => void; + /** Link to navigate to when a clickable-only card is clicked. This cannot be combined with the onClickAction prop. */ + to?: string; + /** Additional props spread to a selectable card input or clickable-only card's button/anchor. */ + selectableActionProps?: any; + /** Flag to indicate whether a clickable-only card's link should open in a new tab/window. */ + isExternalLink?: boolean; + /** Name for the input element of a selectable card. */ + name?: string; + /** @deprecated Flag indicating whether the selectable card input is checked. We recommend using + * the isSelected prop on the card component instead. + */ + isChecked?: boolean; + /** Flag indicating the action is hidden */ + isHidden?: boolean; +} export interface CardHeaderProps extends React.HTMLProps { - /** Content rendered inside the CardHeader */ + /** Content rendered inside the card header */ children?: React.ReactNode; - /** Additional classes added to the CardHeader */ + /** Additional classes added to the card header */ className?: string; + /** Actions of the card header */ + actions?: CardHeaderActionsObject; + /** Selectable actions of the card header */ + selectableActions?: CardHeaderSelectableActionsObject; /** ID of the card header. */ id?: string; /** Callback expandable card */ @@ -18,48 +75,142 @@ export interface CardHeaderProps extends React.HTMLProps { toggleButtonProps?: any; /** Whether to right-align expandable toggle button */ isToggleRightAligned?: boolean; + /** Flag indicating that header wrapping is enabled */ + hasWrap?: boolean; } export const CardHeader: React.FunctionComponent = ({ - children = null, - className = '', + children, + className, + actions, + selectableActions, id, onExpand, toggleButtonProps, isToggleRightAligned, + hasWrap, ...props -}: CardHeaderProps) => ( - - {({ cardId }) => { - const cardHeaderToggle = ( -
    - -
    - ); +}: CardHeaderProps) => { + const randomId = useSSRSafeId(); + + return ( + + {({ cardId, isClickable, isSelectable, isSelected, isDisabled: isCardDisabled }) => { + const cardHeaderToggle = ( +
    +
    + ); - return ( -
    - {onExpand && !isToggleRightAligned && cardHeaderToggle} - {children} - {onExpand && isToggleRightAligned && cardHeaderToggle} -
    - ); - }} -
    -); + const isClickableOrSelectableOnly = (isClickable && !isSelectable) || (isSelectable && !isClickable); + if (actions?.actions && isClickableOrSelectableOnly) { + // eslint-disable-next-line no-console + console.error( + `Card: ${ + isClickable ? 'Clickable' : 'Selectable' + } only cards should not contain any other actions. If you wish to include additional actions, use a clickable and selectable card.` + ); + } + + const isClickableOnlyCard = isClickable && !isSelectable; + if ( + (isClickableOnlyCard || isSelectable) && + !selectableActions?.selectableActionAriaLabel && + !selectableActions?.selectableActionAriaLabelledby + ) { + // eslint-disable-next-line no-console + console.error( + `Card: ${isClickableOnlyCard ? 'Clickable-only cards' : 'Cards with a selectable input'} must have either the selectableActions.selectableActionAriaLabel or selectableActions.selectableActionAriaLabelledby prop passed in order to provide an accessible name to the clickable element.` + ); + } + + const SelectableCardInput = selectableActions?.variant === 'single' ? Radio : Checkbox; + const getSelectableProps = () => ({ + className: css('pf-m-standalone'), + inputClassName: css(selectableActions?.isHidden && 'pf-v6-screen-reader'), + label: <>, + 'aria-label': selectableActions.selectableActionAriaLabel, + 'aria-labelledby': selectableActions.selectableActionAriaLabelledby, + id: selectableActions.selectableActionId ?? `card-selectable-${randomId}`, + name: selectableActions.name, + isDisabled: isCardDisabled, + onChange: selectableActions.onChange, + isChecked: selectableActions.isChecked ?? isSelected, + ...selectableActions.selectableActionProps + }); + + const isClickableLinkCard = selectableActions?.to !== undefined; + const ClickableCardComponent = isClickableLinkCard ? 'a' : 'button'; + const getClickableProps = () => { + const isDisabledLinkCard = isCardDisabled && isClickableLinkCard; + const baseProps = { + className: css( + 'pf-v6-c-card__clickable-action', + isDisabledLinkCard && styles.modifiers.disabled, + selectableActions?.isHidden && 'pf-v6-screen-reader' + ), + id: selectableActions.selectableActionId, + 'aria-label': selectableActions.selectableActionAriaLabel, + 'aria-labelledby': selectableActions.selectableActionAriaLabelledby, + ...selectableActions.selectableActionProps + }; + + if (isClickableLinkCard) { + return { + ...baseProps, + href: selectableActions.to, + ...(isCardDisabled && { tabIndex: -1, 'aria-disabled': true }), + ...(selectableActions.isExternalLink && { target: '_blank' }) + }; + } + + return { ...baseProps, type: 'button', disabled: isCardDisabled, onClick: selectableActions.onClickAction }; + }; + + return ( +
    + {onExpand && !isToggleRightAligned && cardHeaderToggle} + {(actions || (selectableActions && (isClickable || isSelectable))) && ( + + {actions?.actions} + {selectableActions && (isClickable || isSelectable) && ( + + {isSelectable && } + {isClickableOnlyCard && } + + )} + + )} + {children && {children}} + {onExpand && isToggleRightAligned && cardHeaderToggle} +
    + ); + }} +
    + ); +}; CardHeader.displayName = 'CardHeader'; diff --git a/packages/react-core/src/components/Card/CardHeaderMain.tsx b/packages/react-core/src/components/Card/CardHeaderMain.tsx index d01359464e0..e7f4b6d25d8 100644 --- a/packages/react-core/src/components/Card/CardHeaderMain.tsx +++ b/packages/react-core/src/components/Card/CardHeaderMain.tsx @@ -1,4 +1,5 @@ -import * as React from 'react'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Card/card'; export interface CardHeaderMainProps extends React.HTMLProps { /** Content rendered inside the Card Head Main */ @@ -8,11 +9,11 @@ export interface CardHeaderMainProps extends React.HTMLProps { } export const CardHeaderMain: React.FunctionComponent = ({ - children = null, - className = '', + children, + className, ...props }: CardHeaderMainProps) => ( -
    +
    {children}
    ); diff --git a/packages/react-core/src/components/Card/CardSelectableActions.tsx b/packages/react-core/src/components/Card/CardSelectableActions.tsx new file mode 100644 index 00000000000..5a2d2d0e8f2 --- /dev/null +++ b/packages/react-core/src/components/Card/CardSelectableActions.tsx @@ -0,0 +1,20 @@ +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Card/card'; + +export interface CardActionsProps extends React.HTMLProps { + /** Content rendered inside the card action */ + children?: React.ReactNode; + /** Additional classes added to the action */ + className?: string; +} + +export const CardSelectableActions: React.FunctionComponent = ({ + children, + className, + ...props +}: CardActionsProps) => ( +
    + {children} +
    +); +CardSelectableActions.displayName = 'CardSelectableActions'; diff --git a/packages/react-core/src/components/Card/CardSubtitle.tsx b/packages/react-core/src/components/Card/CardSubtitle.tsx new file mode 100644 index 00000000000..63e27ac915a --- /dev/null +++ b/packages/react-core/src/components/Card/CardSubtitle.tsx @@ -0,0 +1,20 @@ +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Card/card'; + +export interface CardSubtitleProps { + /** Content rendered inside the description. */ + children?: React.ReactNode; + /** Id of the description. */ + id?: string; +} + +export const CardSubtitle: React.FunctionComponent = ({ + children = null, + id = '', + ...props +}: CardSubtitleProps) => ( +
    + {children} +
    +); +CardSubtitle.displayName = 'CardSubtitle'; diff --git a/packages/react-core/src/components/Card/CardTitle.tsx b/packages/react-core/src/components/Card/CardTitle.tsx index d6f32314c7a..17333c150f4 100644 --- a/packages/react-core/src/components/Card/CardTitle.tsx +++ b/packages/react-core/src/components/Card/CardTitle.tsx @@ -1,6 +1,8 @@ -import * as React from 'react'; +import { useContext } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Card/card'; +import { CardContext } from './Card'; +import { CardSubtitle } from './CardSubtitle'; export interface CardTitleProps extends React.HTMLProps { /** Content rendered inside the CardTitle */ @@ -8,20 +10,30 @@ export interface CardTitleProps extends React.HTMLProps { /** Additional classes added to the CardTitle */ className?: string; /** Sets the base component to render. defaults to div */ - component?: keyof JSX.IntrinsicElements; + component?: keyof React.JSX.IntrinsicElements; + /** @beta Subtitle of the card title */ + subtitle?: React.ReactNode; } export const CardTitle: React.FunctionComponent = ({ - children = null, - className = '', + children, + className, component = 'div', + subtitle, ...props }: CardTitleProps) => { + const { cardId } = useContext(CardContext); const Component = component as any; + const titleId = cardId ? `${cardId}-title` : ''; + const subtitleId = cardId ? `${cardId}-subtitle` : ''; + return ( - - {children} - +
    + + {children} + + {subtitle && {subtitle}} +
    ); }; CardTitle.displayName = 'CardTitle'; diff --git a/packages/react-core/src/components/Card/__tests__/Card.test.tsx b/packages/react-core/src/components/Card/__tests__/Card.test.tsx index 74f0aead476..42ba729d7ab 100644 --- a/packages/react-core/src/components/Card/__tests__/Card.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/Card.test.tsx @@ -1,107 +1,110 @@ -import React from 'react'; -import { Card } from '../Card'; -import { shallow } from 'enzyme'; - -test('renders with PatternFly Core styles', () => { - const view = shallow().dive(); - expect(view).toMatchSnapshot(); -}); - -test('className is added to the root element', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatchSnapshot(); -}); - -test('extra props are spread to the root element', () => { - const testId = 'card'; - const view = shallow().dive(); - expect(view.prop('data-testid')).toBe(testId); -}); - -test('allows passing in a string as the component', () => { - const component = 'section'; - const view = shallow().dive(); - expect(view.type()).toBe(component); -}); - -test('allows passing in a React Component as the component', () => { - const Component = () =>
    im a div
    ; - const view = shallow().dive(); - expect(view.type()).toBe(Component); -}); - -test('card with isHoverable applied ', () => { - const view = shallow().dive(); - expect(view).toMatchSnapshot(); -}); - -test('card with isCompact applied ', () => { - const view = shallow().dive(); - expect(view).toMatchSnapshot(); -}); - -test('card with isSelectable applied ', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/selectable/); - expect(view.prop('tabIndex')).toBe('0'); -}); - -test('card with isSelectable and isSelected applied ', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/selectable/); - expect(view.prop('className')).toMatch(/selected/); - expect(view.prop('tabIndex')).toBe('0'); -}); +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; -test('card with only isSelected applied - not change', () => { - const view = shallow().dive(); - expect(view.prop('className')).not.toMatch(/selected/); - expect(view.prop('tabIndex')).toBe(undefined); -}); - -test('card with isDisabledRaised applied', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/non-selectable-raised/); -}); - -test('card with isSelectableRaised applied - not change', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/selectable-raised/); - expect(view.prop('tabIndex')).toBe('0'); -}); - -test('card with isSelectableRaised and isSelected applied ', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/selectable-raised/); - expect(view.prop('className')).toMatch(/selected-raised/); - expect(view.prop('tabIndex')).toBe('0'); -}); - -test('card with isFlat applied', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/m-flat/); -}); - -test('card with isExpanded applied', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/m-expanded/); -}); - -test('card with isRounded applied', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/m-rounded/); -}); - -test('card with isLarge applied', () => { - const view = shallow().dive(); - expect(view.prop('className')).toMatch(/m-display-lg/); -}); - -test('card warns when isLarge and isCompact', () => { - const consoleWarnMock = jest.fn(); - global.console = { warn: consoleWarnMock } as any; - shallow(); - expect(consoleWarnMock).toBeCalled(); +import { Card } from '../Card'; +import { createRef } from 'react'; + +describe('Card', () => { + test('renders with PatternFly Core styles', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); + + test('className is added to the root element', () => { + render(card); + expect(screen.getByText('card')).toHaveClass('extra-class'); + }); + + test('extra props are spread to the root element', () => { + const testId = 'card'; + + render(); + expect(screen.getByTestId(testId)).toBeInTheDocument(); + }); + + test('allows passing in a string as the component', () => { + const component = 'section'; + + render(section content); + expect(screen.getByText('section content')).toBeInTheDocument(); + }); + + test('allows passing in a React Component as the component', () => { + const Component = () =>
    im a div
    ; + + render(); + expect(screen.getByText('im a div')).toBeInTheDocument(); + }); + + test('card with isCompact applied ', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); + + test('card with isSelectable applied ', () => { + render(selectable card); + + const card = screen.getByText('selectable card'); + expect(card).toHaveClass('pf-m-selectable'); + }); + + test('card with isSelectable and isSelected applied ', () => { + render( + + selected and selectable card + + ); + + const card = screen.getByText('selected and selectable card'); + expect(card).toHaveClass('pf-m-selectable'); + expect(card).toHaveClass('pf-m-selected'); + }); + + test('card with only isSelected applied - not change', () => { + render(selected card); + + const card = screen.getByText('selected card'); + expect(card).not.toHaveClass('pf-m-selected'); + expect(card.getAttribute('tabindex')).toBeNull(); + }); + + test('card with isExpanded applied', () => { + render(expanded card); + expect(screen.getByText('expanded card')).toHaveClass('pf-m-expanded'); + }); + + test('card with isLarge applied', () => { + render(large card); + expect(screen.getByText('large card')).toHaveClass('pf-m-display-lg'); + }); + + test('card warns when isLarge and isCompact', () => { + const consoleWarnMock = jest.fn(); + global.console = { warn: consoleWarnMock } as any; + + render(); + expect(consoleWarnMock).toHaveBeenCalled(); + }); + + test('card with isGlass applied', () => { + render(glass card); + expect(screen.getByText('glass card')).toHaveClass('pf-m-glass'); + }); + + test('card with variant set to secondary ', () => { + render(secondary card); + + const card = screen.getByText('secondary card'); + expect(card).toHaveClass('pf-m-secondary'); + }); + + test('ref is added to the root element', () => { + const ref = createRef(); + render( + + card + + ); + expect(ref.current).toBe(screen.getByText('card')); + }); }); - - diff --git a/packages/react-core/src/components/Card/__tests__/CardBody.test.tsx b/packages/react-core/src/components/Card/__tests__/CardBody.test.tsx index 3b3af576f34..a1e6478c633 100644 --- a/packages/react-core/src/components/Card/__tests__/CardBody.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/CardBody.test.tsx @@ -1,36 +1,40 @@ -import React from 'react'; +import { render, screen } from '@testing-library/react'; import { CardBody } from '../CardBody'; -import { shallow } from 'enzyme'; -test('renders with PatternFly Core styles', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); +describe('CardBody', () => { + test('renders with PatternFly Core styles', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); -test('className is added to the root element', () => { - const view = shallow(); - expect(view.prop('className')).toMatchSnapshot(); -}); + test('className is added to the root element', () => { + render(); + expect(screen.getByTestId('test-id')).toHaveClass('extra-class'); + }); -test('extra props are spread to the root element', () => { - const testId = 'card-body'; - const view = shallow(); - expect(view.prop('data-testid')).toBe(testId); -}); + test('extra props are spread to the root element', () => { + const testId = 'card-body'; -test('allows passing in a string as the component', () => { - const component = 'section'; - const view = shallow(); - expect(view.type()).toBe(component); -}); + render(); + expect(screen.getByTestId(testId)).toBeInTheDocument(); + }); -test('allows passing in a React Component as the component', () => { - const Component = () =>
    im a div
    ; - const view = shallow(); - expect(view.type()).toBe(Component); -}); + test('allows passing in a string as the component', () => { + const component = 'section'; + + render(section content); + expect(screen.getByText('section content')).toBeInTheDocument(); + }); + + test('allows passing in a React Component as the component', () => { + const Component = () =>
    im a div
    ; + + render(); + expect(screen.getByText('im a div')).toBeInTheDocument(); + }); -test('body with no-fill applied ', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); + test('body with no-fill applied', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/packages/react-core/src/components/Card/__tests__/CardExpandableContent.test.tsx b/packages/react-core/src/components/Card/__tests__/CardExpandableContent.test.tsx index b530d1b0c0f..77b27e573a0 100644 --- a/packages/react-core/src/components/Card/__tests__/CardExpandableContent.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/CardExpandableContent.test.tsx @@ -1,13 +1,12 @@ -import React from 'react'; import { CardContext } from '../Card'; import { CardExpandableContent } from '../CardExpandableContent'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; test('renders successfully', () => { - const view = mount( + const { asFragment } = render( ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Card/__tests__/CardFooter.test.tsx b/packages/react-core/src/components/Card/__tests__/CardFooter.test.tsx index 29d1c7bb0d9..ed7a55d67c2 100644 --- a/packages/react-core/src/components/Card/__tests__/CardFooter.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/CardFooter.test.tsx @@ -1,31 +1,32 @@ -import React from 'react'; +import { render, screen } from '@testing-library/react'; import { CardFooter } from '../CardFooter'; -import { shallow } from 'enzyme'; -test('renders with PatternFly Core styles', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); +describe('CardFooter', () => { + test('renders with PatternFly Core styles', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); -test('className is added to the root element', () => { - const view = shallow(); - expect(view.prop('className')).toMatchSnapshot(); -}); + test('className is added to the root element', () => { + render(text); + expect(screen.getByText('text')).toHaveClass('extra-class'); + }); -test('extra props are spread to the root element', () => { - const testId = 'card-footer'; - const view = shallow(); - expect(view.prop('data-testid')).toBe(testId); -}); + test('extra props are spread to the root element', () => { + const testId = 'card-footer'; -test('allows passing in a string as the component', () => { - const component = 'div'; - const view = shallow(); - expect(view.type()).toBe(component); -}); + render(); + expect(screen.getByTestId(testId)).toBeInTheDocument(); + }); + + test('allows passing in a string as the component', () => { + render(div content); + expect(screen.getByText('div content')).toBeInTheDocument(); + }); -test('allows passing in a React Component as the component', () => { - const Component = () =>
    im a div
    ; - const view = shallow(); - expect(view.type()).toBe(Component); + test('allows passing in a React Component as the component', () => { + const Component = () =>
    im a div
    ; + render(); + expect(screen.getByText('im a div')).toBeInTheDocument(); + }); }); diff --git a/packages/react-core/src/components/Card/__tests__/CardHeadMain.test.tsx b/packages/react-core/src/components/Card/__tests__/CardHeadMain.test.tsx deleted file mode 100644 index cd47817e372..00000000000 --- a/packages/react-core/src/components/Card/__tests__/CardHeadMain.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { CardHeadMain } from '../CardHeadMain'; -import { shallow } from 'enzyme'; - -test('renders with PatternFly Core styles', () => { - const view = shallow(text); - expect(view).toMatchSnapshot(); -}); - -test('className is added to the root element', () => { - const view = shallow(text); - expect(view.prop('className')).toMatchSnapshot(); -}); - -test('extra props are spread to the root element', () => { - const testId = 'card-head-main'; - const view = shallow(); - expect(view.prop('data-testid')).toBe(testId); -}); diff --git a/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx b/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx index 8e513349ce8..8a4ac4d38f3 100644 --- a/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx @@ -1,25 +1,357 @@ -import React from 'react'; -import { CardTitle } from '../CardTitle'; +import { render, screen } from '@testing-library/react'; +import styles from '@patternfly/react-styles/css/components/Card/card'; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; import { CardHeader } from '../CardHeader'; -import { shallow, mount } from 'enzyme'; +import { CardContext } from '../Card'; -test('renders with PatternFly Core styles', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); +describe('CardHeader', () => { + test('onExpand adds the toggle button', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); -test('className is added to the root element', () => { - const view = shallow(); - expect(view.prop('className')).toMatchSnapshot(); -}); + test('actions are rendered', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); + + test(`Should render CardHeader without ${styles.modifiers.wrap} by default`, () => { + render(); -test('extra props are spread to the root element', () => { - const testId = 'card-header'; - const view = shallow(); - expect(view.prop('data-testid')).toBe(testId); + expect(screen.getByTestId('card-header')).not.toHaveClass(styles.modifiers.wrap); + }); + + test(`Should render CardHeader with ${styles.modifiers.wrap} class when hasWrap is true`, () => { + render(); + + expect(screen.getByTestId('card-header-will-wrap')).toHaveClass(styles.modifiers.wrap); + }); }); -test('onExpand adds the toggle button', () => { - const view = mount(); - expect(view).toMatchSnapshot(); +// TODO: check if hasNoOffset for actions/selectableActions and className for selectableActions render +describe('Card with actions and selectableActions', () => { + test('Does not render selectable or clickable actions by default', () => { + render(Test); + + expect(screen.queryByRole('checkbox')).not.toBeInTheDocument(); + expect(screen.queryByRole('button')).not.toBeInTheDocument(); + expect(screen.queryByRole('link')).not.toBeInTheDocument(); + }); + + test('Renders checkbox input when Card has isSelectable and selectableActions.variant = "multiple"', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeInTheDocument(); + }); + test('Renders checkbox input by default when Card has isSelectable and selectableActions is passed with any props', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeInTheDocument(); + }); + test('Renders radio input when Card has isSelectable and selectableActions.variant = "single"', () => { + render( + + Test + + ); + + expect(screen.getByRole('radio')).toBeInTheDocument(); + }); + test('Renders default ID for selectable card input when selectableActions.selectableActionId is not passed', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox').getAttribute('id')).toMatch(/^card-selectable/); + }); + test('Renders custom ID for selectable card input when selectableActions.selectableActionId is passed', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toHaveAttribute('id', 'custom-id'); + }); + test('Renders name on a selectable card input', () => { + render( + + Test + + ); + + expect(screen.getByRole('radio')).toHaveAttribute('name', 'test'); + }); + test('Renders a selectable card input as not checked by default', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).not.toBeChecked(); + }); + test('Renders a selectable card input as checked when Card has isSelected = true', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeChecked(); + }); + test('Renders a selectable card input as checked when deprecated selectableActions.isChecked is true', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeChecked(); + }); + test('Renders additional props on selectable card input when selectableActions.selectableActionProps is passed', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('checkbox')).toHaveAttribute('style'); + }); + + test('Does not call onChange for selectable card when card is not clicked', async () => { + const user = userEvent.setup(); + const onChangeMock = jest.fn(); + + render( + <> + + + Test + + + ); + + await user.click(screen.getByRole('button', { name: 'Test click' })); + expect(onChangeMock).not.toHaveBeenCalled(); + }); + test('Calls onChange for selectable card when card is clicked', async () => { + const user = userEvent.setup(); + const onChangeMock = jest.fn(); + + render( + + Test + + ); + + const labelElement = document.querySelector('label'); + await user.click(labelElement as HTMLElement); + expect(onChangeMock).toHaveBeenCalled(); + }); + + test('Renders button element when Card has isClickable and selectableActions.onClickAction is passed"', () => { + render( + + {} }}>Test + + ); + + expect(screen.getByRole('button')).toBeInTheDocument(); + }); + test('Renders anchor element when Card has isClickable and selectableActions.to is passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toBeInTheDocument(); + }); + test('Renders href when Card has isClickable and selectableActions.to is passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAttribute('href', '#some-id'); + }); + test('Does not render ID on clickable element when selectableActions.selectableActionId is not passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).not.toHaveAttribute('id'); + }); + test('Renders ID on clickable element when selectableActions.selectableActionId is passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAttribute('id', 'custom-id'); + }); + test('Renders additional props on clickable element when selectableActions.selectableActionProps is passed', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('link')).toHaveAttribute('style'); + }); + test('Does not render target="_blank" on clickable card anchor element by default"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).not.toHaveAttribute('target'); + }); + test('Renders target="_blank" on clickable card anchor element when selectableActions.isExternalLink is true"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAttribute('target', '_blank'); + }); + test('Calls onClickAction for clickable card when card is clicked', async () => { + const user = userEvent.setup(); + const onClickMock = jest.fn(); + + render( + + Test + + ); + + await user.click(screen.getByRole('button')); + expect(onClickMock).toHaveBeenCalled(); + }); + + test('Throws error when Card is either clickable or selectable only and has actions prop passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Toggle }} + selectableActions={{ to: '#', selectableActionAriaLabel: 'Link' }} + > + Test + + + ); + + expect(errorMock).toHaveBeenCalled(); + }); + test('Does not throw error when Card is both clickable and selectable and has actions prop passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Toggle }} + selectableActions={{ to: '#', selectableActionAriaLabel: 'Link' }} + > + Test + + + ); + + expect(errorMock).not.toHaveBeenCalled(); + }); + test('Throws error when Card has isClickable and selectableActions.selectableActionAriaLabel or selectableActions.selectableActionAriaLabelledby is not passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Test + + ); + + expect(errorMock).toHaveBeenCalled(); + }); + test('Throws error when Card has isSelectable and selectableActions.selectableActionAriaLabel or selectableActions.selectableActionAriaLabelledby is not passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Test + + ); + + expect(errorMock).toHaveBeenCalled(); + }); + + test('Renders accessible name on selectable card input when selectableActions.selectableActionAriaLabel is passed', () => { + const accessibleName = 'Accessible name'; + render( + + + Test + + + ); + + expect(screen.getByRole('checkbox')).toHaveAccessibleName(accessibleName); + }); + test('Renders accessible name on selectable card input when selectableActions.selectableActionAriaLabelledby is passed', () => { + const labelingId = 'labelling-id'; + const accessibleName = 'Accessible name'; + render( + + +
    {accessibleName}
    +
    +
    + ); + + expect(screen.getByRole('checkbox')).toHaveAccessibleName(accessibleName); + }); + test('Renders accessible name on clickable card clickable element when selectableActions.selectableActionAriaLabel is passed', () => { + const accessibleName = 'Accessible name'; + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAccessibleName(accessibleName); + }); + test('Renders accessible name on clickable card clickable element when selectableActions.selectableActionAriaLabelledby is passed', () => { + const labelingId = 'labelling-id'; + const accessibleName = 'Accessible name'; + render( + + +
    {accessibleName}
    +
    +
    + ); + + expect(screen.getByRole('link')).toHaveAccessibleName(accessibleName); + }); }); diff --git a/packages/react-core/src/components/Card/__tests__/CardHeaderMain.test.tsx b/packages/react-core/src/components/Card/__tests__/CardHeaderMain.test.tsx index 98066c5d2d7..dd393d0d845 100644 --- a/packages/react-core/src/components/Card/__tests__/CardHeaderMain.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/CardHeaderMain.test.tsx @@ -1,19 +1,21 @@ -import React from 'react'; +import { render, screen } from '@testing-library/react'; import { CardHeaderMain } from '../CardHeaderMain'; -import { shallow } from 'enzyme'; -test('renders with PatternFly Core styles', () => { - const view = shallow(text); - expect(view).toMatchSnapshot(); -}); +describe('CardHeaderMain', () => { + test('renders with PatternFly Core styles', () => { + const { asFragment } = render(text); + expect(asFragment()).toMatchSnapshot(); + }); -test('className is added to the root element', () => { - const view = shallow(text); - expect(view.prop('className')).toMatchSnapshot(); -}); + test('className is added to the root element', () => { + render(text); + expect(screen.getByText('text')).toHaveClass('extra-class'); + }); + + test('extra props are spread to the root element', () => { + const testId = 'card-head-main'; -test('extra props are spread to the root element', () => { - const testId = 'card-head-main'; - const view = shallow(); - expect(view.prop('data-testid')).toBe(testId); + render(); + expect(screen.getByTestId(testId)).toBeInTheDocument(); + }); }); diff --git a/packages/react-core/src/components/Card/__tests__/CardSelectableActions.test.tsx b/packages/react-core/src/components/Card/__tests__/CardSelectableActions.test.tsx new file mode 100644 index 00000000000..3f9798629cf --- /dev/null +++ b/packages/react-core/src/components/Card/__tests__/CardSelectableActions.test.tsx @@ -0,0 +1,31 @@ +import { render, screen } from '@testing-library/react'; +import { CardSelectableActions } from '../CardSelectableActions'; + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Renders without children', () => { + render(); + + expect(screen.getByTestId('card-selectable-actions')).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test('Renders with class name pf-v6-c-card__selectable-actions', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('pf-v6-c-card__selectable-actions'); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('test-class'); +}); diff --git a/packages/react-core/src/components/Card/__tests__/CardSubtitle.test.tsx b/packages/react-core/src/components/Card/__tests__/CardSubtitle.test.tsx new file mode 100644 index 00000000000..1a71e952344 --- /dev/null +++ b/packages/react-core/src/components/Card/__tests__/CardSubtitle.test.tsx @@ -0,0 +1,48 @@ +import { render, screen } from '@testing-library/react'; +import { CardSubtitle } from '../CardSubtitle'; +import styles from '@patternfly/react-styles/css/components/Card/card'; + +test('Renders without children', () => { + render( +
    + +
    + ); + + expect(screen.getByTestId('container').firstChild).toBeVisible(); +}); + +test('Renders with children', () => { + render(Subtitle content); + + expect(screen.getByText('Subtitle content')).toBeInTheDocument(); +}); + +test(`Renders with class ${styles.cardSubtitle} by default`, () => { + render(Subtitle content); + + expect(screen.getByText('Subtitle content')).toHaveClass(styles.cardSubtitle, { exact: true }); +}); + +test('Renders with id when passed', () => { + render(Subtitle content); + + expect(screen.getByText('Subtitle content')).toHaveAttribute('id', 'subtitle-id'); +}); + +test('extra props are spread to the root element', () => { + const testId = 'card-subtitle'; + + render(); + expect(screen.getByTestId(testId)).toBeInTheDocument(); +}); + +test('Matches snapshot without children', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Matches snapshot with children', () => { + const { asFragment } = render(Subtitle content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Card/__tests__/CardTitle.test.tsx b/packages/react-core/src/components/Card/__tests__/CardTitle.test.tsx new file mode 100644 index 00000000000..ff7b10cb055 --- /dev/null +++ b/packages/react-core/src/components/Card/__tests__/CardTitle.test.tsx @@ -0,0 +1,31 @@ +import { render, screen } from '@testing-library/react'; +import { CardTitle } from '../CardTitle'; + +test('Renders with custom class when passed', () => { + render(text); + expect(screen.getByText('text')).toHaveClass('extra-class'); +}); + +test('Does not render with card subtitle by default', () => { + render(text); + + expect(screen.queryByText('text')?.nextElementSibling).not.toBeInTheDocument(); +}); + +test('Renders with card subtitle when subtitle is passed', () => { + render(text); + + expect(screen.getByText('subtitle content')).toBeInTheDocument(); +}); + +test('extra props are spread to the root element', () => { + const testId = 'card-header'; + + render(); + expect(screen.getByTestId(testId)).toBeInTheDocument(); +}); + +test('Matches snapshot', () => { + const { asFragment } = render(text); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Card/__tests__/Generated/Card.test.tsx b/packages/react-core/src/components/Card/__tests__/Generated/Card.test.tsx deleted file mode 100644 index 15122db4c03..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/Card.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Card } from '../../Card'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Card should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} className={"''"} component={'article'} isHoverable={false} isCompact={false} /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Card/__tests__/Generated/CardActions.test.tsx b/packages/react-core/src/components/Card/__tests__/Generated/CardActions.test.tsx index 40aa7358712..5275d6e1a45 100644 --- a/packages/react-core/src/components/Card/__tests__/Generated/CardActions.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/Generated/CardActions.test.tsx @@ -1,13 +1,12 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { CardActions } from '../../CardActions'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('CardActions should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} />); - expect(view).toMatchSnapshot(); + const { asFragment } = render(ReactNode} className={"''"} />); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Card/__tests__/Generated/CardBody.test.tsx b/packages/react-core/src/components/Card/__tests__/Generated/CardBody.test.tsx deleted file mode 100644 index 86c830b8f2c..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/CardBody.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { CardBody } from '../../CardBody'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('CardBody should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} component={'div'} isFilled={true} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Card/__tests__/Generated/CardFooter.test.tsx b/packages/react-core/src/components/Card/__tests__/Generated/CardFooter.test.tsx deleted file mode 100644 index 4f3eeaeb4c6..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/CardFooter.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { CardFooter } from '../../CardFooter'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('CardFooter should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} component={'div'} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Card/__tests__/Generated/CardHead.test.tsx b/packages/react-core/src/components/Card/__tests__/Generated/CardHead.test.tsx deleted file mode 100644 index 6205c207a8c..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/CardHead.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { CardHeader } from '../../CardHeader'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('CardHeader should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Card/__tests__/Generated/CardHeader.test.tsx b/packages/react-core/src/components/Card/__tests__/Generated/CardHeader.test.tsx deleted file mode 100644 index 8fefdab3bd8..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/CardHeader.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { CardTitle } from '../../CardTitle'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('CardTitle should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/Card.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/Card.test.tsx.snap deleted file mode 100644 index 67c8d702ef4..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/Card.test.tsx.snap +++ /dev/null @@ -1,22 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Card should match snapshot (auto-generated) 1`] = ` - -
    - ReactNode -
    -
    -`; diff --git a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardActions.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardActions.test.tsx.snap index bcc461b478d..4ef441fa423 100644 --- a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardActions.test.tsx.snap +++ b/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardActions.test.tsx.snap @@ -1,9 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`CardActions should match snapshot (auto-generated) 1`] = ` -
    - ReactNode -
    + +
    + ReactNode +
    +
    `; diff --git a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardBody.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardBody.test.tsx.snap deleted file mode 100644 index ae7134a14c3..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardBody.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CardBody should match snapshot (auto-generated) 1`] = ` -
    - ReactNode -
    -`; diff --git a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardFooter.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardFooter.test.tsx.snap deleted file mode 100644 index 70c23781ad4..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardFooter.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CardFooter should match snapshot (auto-generated) 1`] = ` -
    - ReactNode -
    -`; diff --git a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardHead.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardHead.test.tsx.snap deleted file mode 100644 index 0ecca4c0013..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardHead.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CardHeader should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardHeader.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardHeader.test.tsx.snap deleted file mode 100644 index 62395ca666f..00000000000 --- a/packages/react-core/src/components/Card/__tests__/Generated/__snapshots__/CardHeader.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CardTitle should match snapshot (auto-generated) 1`] = ` -
    - ReactNode -
    -`; diff --git a/packages/react-core/src/components/Card/__tests__/__snapshots__/Card.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/__snapshots__/Card.test.tsx.snap index 459c896de70..cad89cf924a 100644 --- a/packages/react-core/src/components/Card/__tests__/__snapshots__/Card.test.tsx.snap +++ b/packages/react-core/src/components/Card/__tests__/__snapshots__/Card.test.tsx.snap @@ -1,33 +1,25 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`card with isCompact applied 1`] = ` -
    +exports[`Card card with isCompact applied 1`] = ` + +
    + `; -exports[`card with isHoverable applied 1`] = ` -
    -`; - -exports[`className is added to the root element 1`] = `"pf-c-card extra-class"`; - -exports[`renders with PatternFly Core styles 1`] = ` -
    +exports[`Card renders with PatternFly Core styles 1`] = ` + +
    + `; diff --git a/packages/react-core/src/components/Card/__tests__/__snapshots__/CardBody.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardBody.test.tsx.snap index 23fa5c9e969..72419a20797 100644 --- a/packages/react-core/src/components/Card/__tests__/__snapshots__/CardBody.test.tsx.snap +++ b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardBody.test.tsx.snap @@ -1,15 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`body with no-fill applied 1`] = ` -
    +exports[`CardBody body with no-fill applied 1`] = ` + +
    + `; -exports[`className is added to the root element 1`] = `"pf-c-card__body extra-class"`; - -exports[`renders with PatternFly Core styles 1`] = ` -
    +exports[`CardBody renders with PatternFly Core styles 1`] = ` + +
    + `; diff --git a/packages/react-core/src/components/Card/__tests__/__snapshots__/CardExpandableContent.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardExpandableContent.test.tsx.snap index 8d4c11bb53d..68ab1a6fa38 100644 --- a/packages/react-core/src/components/Card/__tests__/__snapshots__/CardExpandableContent.test.tsx.snap +++ b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardExpandableContent.test.tsx.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders successfully 1`] = ` - +
    - + `; diff --git a/packages/react-core/src/components/Card/__tests__/__snapshots__/CardFooter.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardFooter.test.tsx.snap index ae7755c230a..7941114e883 100644 --- a/packages/react-core/src/components/Card/__tests__/__snapshots__/CardFooter.test.tsx.snap +++ b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardFooter.test.tsx.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`className is added to the root element 1`] = `"pf-c-card__footer extra-class"`; - -exports[`renders with PatternFly Core styles 1`] = ` -
    +exports[`CardFooter renders with PatternFly Core styles 1`] = ` + + - } - entryDelay={2000} - exitDelay={1000} - maxWidth="500px" - position="right" - trigger="mouseenter focus click" -> - - +
    +
    + Button content +
    +
    +

    + exitDelay: 0 +

    +

    + entryDelay: 300 +

    +

    + maxWidth: 100px +

    +

    + position: top +

    +
    + onTooltipHidden clicker + + +
    + `; diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap index aa53a36d2f1..81f138a09ae 100644 --- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap +++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyExpanded.test.tsx.snap @@ -1,30 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`expanded code content render 1`] = ` -
    -
    -    {
    -    "name": "@patternfly/react-core",
    -    "version": "1.33.2"
    -  }
    -  
    -
    -`; - -exports[`expanded content render 1`] = ` -
    - This is my text -
    +exports[`Matches snapshot 1`] = ` + +
    + Expanded content +
    +
    `; diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap index 7b3e299f77d..c318dccc369 100644 --- a/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap +++ b/packages/react-core/src/components/ClipboardCopy/__tests__/__snapshots__/ClipboardCopyToggle.test.tsx.snap @@ -1,22 +1,37 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`toggle button render 1`] = ` - +exports[`Matches snapshot 1`] = ` + + + `; diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopy.md b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopy.md index 7199b35ef76..e49c538f18a 100644 --- a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopy.md +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopy.md @@ -1,177 +1,74 @@ --- id: Clipboard copy section: components -cssPrefix: pf-c-copyclipboard +cssPrefix: pf-v6-c-clipboard-copy propComponents: ['ClipboardCopy', 'ClipboardCopyButton'] +ouia: true --- +import { Fragment, useEffect, useState } from 'react'; import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; ## Examples ### Basic -```js -import React from 'react'; -import { ClipboardCopy } from '@patternfly/react-core'; - -This is editable; +```ts file="./ClipboardCopyBasic.tsx" ``` ### Read Only -```js -import React from 'react'; -import { ClipboardCopy } from '@patternfly/react-core'; - -This is read-only; +```ts file="./ClipboardCopyReadOnly.tsx" ``` ### Expanded -```js -import React from 'react'; -import { ClipboardCopy, ClipboardCopyVariant } from '@patternfly/react-core'; - - - Got a lot of text here, need to see all of it? Click that arrow on the left side and check out the resulting - expansion. -; +```ts file="./ClipboardCopyExpanded.tsx" ``` ### Read only expanded -```js -import React from 'react'; -import { ClipboardCopy, ClipboardCopyVariant } from '@patternfly/react-core'; - - - Got a lot of text here, need to see all of it? Click that arrow on the left side and check out the resulting - expansion. -; +```ts file="./ClipboardCopyReadOnlyExpanded.tsx" ``` ### Read only expanded by default -```js -import React from 'react'; -import { ClipboardCopy, ClipboardCopyVariant } from '@patternfly/react-core'; - - - Got a lot of text here, need to see all of it? Click that arrow on the left side and check out the resulting - expansion. -; +```ts file="./ClipboardCopyReadOnlyExpandedByDefault.tsx" ``` ### Expanded with array -```js -import React from 'react'; -import { ClipboardCopy, ClipboardCopyVariant } from '@patternfly/react-core'; - -ClipboardCopyArrayOfElements = () => { - let text = [ - 'Got a lot of text here,', - 'need to see all of it?', - 'Click that arrow on the left side and check out the resulting expansion.' - ]; - return {text.join(' ')}; -}; +```ts file="./ClipboardCopyExpandedWithArray.tsx" ``` ### JSON object (wrap code with pre) -```js -import React from 'react'; -import { ClipboardCopy, ClipboardCopyVariant } from '@patternfly/react-core'; - - - {`{ "menu": { - "id": "file", - "value": "File", - "popup": { - "menuitem": [ - {"value": "New", "onclick": "CreateNewDoc()"}, - {"value": "Open", "onclick": "OpenDoc()"}, - {"value": "Close", "onclick": "CloseDoc()"} - ] - } -}} `} -; +```ts file="./ClipboardCopyJSONObject.tsx" ``` ### Inline compact -```js -import React from 'react'; -import { ClipboardCopy } from '@patternfly/react-core'; - -2.3.4-2-redhat; +```ts file="./ClipboardCopyInlineCompact.tsx" ``` ### Inline compact code -```js -import React from 'react'; -import { ClipboardCopy } from '@patternfly/react-core'; - - - 2.3.4-2-redhat -; +```ts file="./ClipboardCopyInlineCompactCode.tsx" ``` ### Inline compact with additional action -```js -import React from 'react'; -import { ClipboardCopy, ClipboardCopyAction, Button } from '@patternfly/react-core'; -import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; - - - - - } -> - 2.3.4-2-redhat -; +```ts file="./ClipboardCopyInlineCompactWithAdditionalAction.tsx" ``` ### Inline compact in sentence -```js -import React from 'react'; -import { ClipboardCopy } from '@patternfly/react-core'; - - - Basic -
    - Lorem ipsum {2.3.4-2-redhat} dolor sit amet. -

    - Long copy string -
    - Lorem ipsum dolor sit amet, consectetur adipiscing elit.{' '} - { - - https://app.openshift.io/path/sub-path/sub-sub-path/?runtime=quarkus/12345678901234567890/abcdefghijklmnopqrstuvwxyz1234567890 - - }{' '} - Mauris luctus, libero nec dapibus ultricies, urna purus pretium mauris, ullamcorper pharetra lacus nibh vitae enim. -

    - Long copy string in block -
    - Lorem ipsum dolor sit amet, consectetur adipiscing elit.{' '} - { - - https://app.openshift.io/path/sub-path/sub-sub-path/?runtime=quarkus/12345678901234567890/abcdefghijklmnopqrstuvwxyz1234567890 - - }{' '} - Mauris luctus, libero nec dapibus ultricies, urna purus pretium mauris, ullamcorper pharetra lacus nibh vitae enim. -
    ; +```ts file="./ClipboardCopyInlineCompactInSentence.tsx" +``` + +### Inline compact with truncation + +You can control the truncation for an `inline-compact` variant by passing the `truncation` property. The following example shows the different ways to use the property: passing a boolean will apply default truncation, while passing an object of `TruncateProps` offers more fine-tuned control over the truncation behavior. + +```ts file="./ClipboardCopyInlineCompactTruncation.tsx" ``` diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyBasic.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyBasic.tsx new file mode 100644 index 00000000000..f7b8e3ee881 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyBasic.tsx @@ -0,0 +1,7 @@ +import { ClipboardCopy } from '@patternfly/react-core'; + +export const ClipboardCopyBasic: React.FunctionComponent = () => ( + + This is editable + +); diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyExpanded.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyExpanded.tsx new file mode 100644 index 00000000000..3f5e4a9aa65 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyExpanded.tsx @@ -0,0 +1,14 @@ +import { ClipboardCopy, ClipboardCopyVariant } from '@patternfly/react-core'; + +export const ClipboardCopyExpanded: React.FunctionComponent = () => ( + + Got a lot of text here, need to see all of it? Click that arrow on the left side and check out the resulting + expansion. + +); diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyExpandedWithArray.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyExpandedWithArray.tsx new file mode 100644 index 00000000000..67505306924 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyExpandedWithArray.tsx @@ -0,0 +1,19 @@ +import { ClipboardCopy, ClipboardCopyVariant } from '@patternfly/react-core'; + +const text = [ + 'Got a lot of text here,', + 'need to see all of it?', + 'Click that arrow on the left side and check out the resulting expansion.' +]; + +export const ClipboardCopyExpandedWithArray: React.FunctionComponent = () => ( + + {text.join(' ')} + +); diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompact.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompact.tsx new file mode 100644 index 00000000000..ddf5cf2b5e4 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompact.tsx @@ -0,0 +1,6 @@ +import { ClipboardCopy } from '@patternfly/react-core'; +export const ClipboardCopyInlineCompact: React.FunctionComponent = () => ( + + 2.3.4-2-redhat + +); diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactCode.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactCode.tsx new file mode 100644 index 00000000000..098dd3c5013 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactCode.tsx @@ -0,0 +1,13 @@ +import { ClipboardCopy } from '@patternfly/react-core'; + +export const ClipboardCopyInlineCompactCode: React.FunctionComponent = () => ( + + 2.3.4-2-redhat + +); diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactInSentence.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactInSentence.tsx new file mode 100644 index 00000000000..e6cd9e4be17 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactInSentence.tsx @@ -0,0 +1,52 @@ +import { Fragment } from 'react'; +import { ClipboardCopy } from '@patternfly/react-core'; + +export const ClipboardCopyInlineCompactInSentence: React.FunctionComponent = () => ( + + Basic +
    + Lorem ipsum{' '} + { + + 2.3.4-2-redhat + + } + dolor sit amet. +

    + Long copy string +
    + Lorem ipsum dolor sit amet, consectetur adipiscing elit.{' '} + { + + https://app.openshift.io/path/sub-path/sub-sub-path/?runtime=quarkus/12345678901234567890/abcdefghijklmnopqrstuvwxyz1234567890 + + }{' '} + Mauris luctus, libero nec dapibus ultricies, urna purus pretium mauris, ullamcorper pharetra lacus nibh vitae enim. +

    + Long copy string in block +
    + Lorem ipsum dolor sit amet, consectetur adipiscing elit.{' '} + { + + https://app.openshift.io/path/sub-path/sub-sub-path/?runtime=quarkus/12345678901234567890/abcdefghijklmnopqrstuvwxyz1234567890 + + }{' '} + Mauris luctus, libero nec dapibus ultricies, urna purus pretium mauris, ullamcorper pharetra lacus nibh vitae enim. +
    +); diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactTruncation.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactTruncation.tsx new file mode 100644 index 00000000000..46609dcc245 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactTruncation.tsx @@ -0,0 +1,27 @@ +import { ClipboardCopy } from '@patternfly/react-core'; +export const ClipboardCopyInlineCompactTruncation: React.FunctionComponent = () => ( + <> + + This lengthy, copyable content will be truncated with default settings when the truncation prop is simply set to + true. This is useful for quickly applying truncation without needing to worry about any other properties to set. + +
    +
    + + This lengthy, copyable content will be truncated with customized settings when the truncation prop is passed an + object containing Truncate props. This is useful for finetuning truncation for your particular use-case. + + +); diff --git a/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactWithAdditionalAction.tsx b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactWithAdditionalAction.tsx new file mode 100644 index 00000000000..c0eb8334ceb --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/examples/ClipboardCopyInlineCompactWithAdditionalAction.tsx @@ -0,0 +1,37 @@ +import { useState } from 'react'; +import { ClipboardCopy, ClipboardCopyAction, Button, Tooltip } from '@patternfly/react-core'; +import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; + +export const ClipboardCopyInlineCompactWithAdditionalAction: React.FunctionComponent = () => { + const [isRunning, setisRunning] = useState(false); + const runText: string = 'Run in web terminal'; + const doneRunText: string = 'Running in web terminal'; + return ( + + setisRunning(false)} + > +
    }>children); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/CodeBlock/__tests__/CodeBlockAction.test.tsx b/packages/react-core/src/components/CodeBlock/__tests__/CodeBlockAction.test.tsx new file mode 100644 index 00000000000..01ee459ef71 --- /dev/null +++ b/packages/react-core/src/components/CodeBlock/__tests__/CodeBlockAction.test.tsx @@ -0,0 +1,25 @@ +import { render, screen } from '@testing-library/react'; +import { CodeBlockAction } from '../CodeBlockAction'; +import styles from '@patternfly/react-styles/css/components/CodeBlock/code-block'; + +test('CodeBlockAction renders', () => { + render(action); + expect(screen.getByText('action')).toBeVisible(); +}); + +test(`CodeBlockAction renders with class ${styles.codeBlockActions}-item by default`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(`${styles.codeBlockActions}-item`); +}); + +test('CodeBlockAction renders with custom class', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('tester'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(children); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/CodeBlock/__tests__/CodeBlockCode.test.tsx b/packages/react-core/src/components/CodeBlock/__tests__/CodeBlockCode.test.tsx new file mode 100644 index 00000000000..91a9573271c --- /dev/null +++ b/packages/react-core/src/components/CodeBlock/__tests__/CodeBlockCode.test.tsx @@ -0,0 +1,35 @@ +import { render, screen } from '@testing-library/react'; +import { CodeBlockCode } from '../CodeBlockCode'; +import styles from '@patternfly/react-styles/css/components/CodeBlock/code-block'; + +test('CodeBlockCode renders', () => { + render(action); + expect(screen.getByText('action')).toBeVisible(); +}); + +test(`Renders with class ${styles.codeBlockPre} by default`, () => { + render( + + Test + + ); + + expect(screen.getByTestId('code-block-code')).toHaveClass(`${styles.codeBlockPre} test`); +}); + +test(`Renders with class ${styles.codeBlockCode} by default`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.codeBlockCode); +}); + +test('Renders with custom class', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('tester'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(children); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlock.test.tsx.snap b/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlock.test.tsx.snap index c7bbdfa4fb3..a8a9dff729e 100644 --- a/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlock.test.tsx.snap +++ b/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlock.test.tsx.snap @@ -1,86 +1,26 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`CodeBlock renders successfully 1`] = ` -
    +exports[`Matches the snapshot 1`] = ` +
    -
    -
    - test text -
    -
    -`; - -exports[`CodeBlock with components renders successfully 1`] = ` - - button - - } -> -
    -
    - -
    - button -
    -
    +
    + actions +
    - -
    -          
    -            inside pre/code tags
    -          
    -        
    -
    - test outer text + children
    -
    -`; - -exports[`CodeBlockAction renders successfully 1`] = ` -
    - action -
    -`; - -exports[`CodeBlockCode renders successfully 1`] = ` -
    -  
    -    action
    -  
    -
    +
    `; diff --git a/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlockAction.test.tsx.snap b/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlockAction.test.tsx.snap new file mode 100644 index 00000000000..3947a300859 --- /dev/null +++ b/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlockAction.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + children +
    +
    +`; diff --git a/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlockCode.test.tsx.snap b/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlockCode.test.tsx.snap new file mode 100644 index 00000000000..870e872ed3f --- /dev/null +++ b/packages/react-core/src/components/CodeBlock/__tests__/__snapshots__/CodeBlockCode.test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    +    
    +      children
    +    
    +  
    +
    +`; diff --git a/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md b/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md index 3e9eadc7470..da8e7bb5b1c 100644 --- a/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md +++ b/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md @@ -1,214 +1,28 @@ --- id: Code block section: components -cssPrefix: pf-c-code-block +cssPrefix: pf-v6-c-code-block propComponents: ['CodeBlock', 'CodeBlockAction', 'CodeBlockCode'] --- +import { Fragment, useState } from 'react'; import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; -## Examples - -### Basic - -```js -import React from 'react'; -import { CodeBlock, CodeBlockAction, CodeBlockCode, ClipboardCopyButton, Button } from '@patternfly/react-core'; -import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; -import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; - -class BasicCodeBlock extends React.Component { - constructor(props) { - super(props); - this.timer = null; - - this.state = { - copied: false - }; +**Important note:** to format code exactly as it is, you should use String.raw\`your code here\`. - this.clipboardCopyFunc = (event, text) => { - const clipboard = event.currentTarget.parentElement; - const el = document.createElement('textarea'); - el.value = text.toString(); - clipboard.appendChild(el); - el.select(); - document.execCommand('copy'); - clipboard.removeChild(el); - }; +Using **String.raw\`\`** will keep all the special characters like `\n` or `\t`. - this.onClick = (event, text) => { - if (this.timer) { - window.clearTimeout(this.timer); - this.setState({ copied: false }); - } - this.clipboardCopyFunc(event, text); - this.setState({ copied: true }, () => { - this.timer = window.setTimeout(() => { - this.setState({ copied: false }); - this.timer = null; - }, 1000); - }); - }; - } +## Examples - render() { - const code = `apiVersion: helm.openshift.io/v1beta1/ -kind: HelmChartRepository -metadata: -name: azure-sample-repo -spec: -connectionConfig: -url: https://raw.githubusercontent.com/Azure-Samples/helm-charts/master/docs`; +### Basic - const actions = ( - - - this.onClick(e, code)} - exitDelay={600} - maxWidth="110px" - variant="plain" - > - {this.state.copied ? 'Successfully copied to clipboard!' : 'Copy to clipboard'} - - - - - - - ); +```ts file="./CodeBlockBasic.tsx" - return ( - - {code} - - ); - } -} ``` ### Expandable -```js -import React from 'react'; -import { - CodeBlock, - CodeBlockAction, - CodeBlockCode, - ClipboardCopyButton, - ExpandableSection, - ExpandableSectionToggle, - Button -} from '@patternfly/react-core'; -import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; -import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; - -class BasicCodeBlock extends React.Component { - constructor(props) { - super(props); - this.timer = null; - - this.state = { - isExpanded: false, - copied: false - }; - - this.onToggle = isExpanded => { - this.setState({ - isExpanded - }); - }; - - this.clipboardCopyFunc = (event, text) => { - const clipboard = event.currentTarget.parentElement; - const el = document.createElement('textarea'); - el.value = text.toString(); - clipboard.appendChild(el); - el.select(); - document.execCommand('copy'); - clipboard.removeChild(el); - }; - - this.onClick = (event, text) => { - if (this.timer) { - window.clearTimeout(this.timer); - this.setState({ copied: false }); - } - this.clipboardCopyFunc(event, text); - this.setState({ copied: true }, () => { - this.timer = window.setTimeout(() => { - this.setState({ copied: false }); - this.timer = null; - }, 1000); - }); - }; - } - - render() { - const { isExpanded } = this.state; - - const copyBlock = `apiVersion: helm.openshift.io/v1beta1/ -kind: HelmChartRepository -metadata: -name: azure-sample-repo -spec: -connectionConfig: -url: https://raw.githubusercontent.com/Azure-Samples/helm-charts/master/docs`; - - const code = `apiVersion: helm.openshift.io/v1beta1/ -kind: HelmChartRepository -metadata: -name: azure-sample-repo`; - const expandedCode = `spec: -connectionConfig: -url: https://raw.githubusercontent.com/Azure-Samples/helm-charts/master/docs`; +```ts file="./CodeBlockExpandable.tsx" - const actions = ( - - - this.onClick(e, copyBlock)} - exitDelay={600} - maxWidth="110px" - variant="plain" - > - {this.state.copied ? 'Successfully copied to clipboard!' : 'Copy to clipboard'} - - - - - - - ); - return ( - - - {code} - - {expandedCode} - - - - {isExpanded ? 'Show Less' : 'Show More'} - - - ); - } -} ``` diff --git a/packages/react-core/src/components/CodeBlock/examples/CodeBlockBasic.tsx b/packages/react-core/src/components/CodeBlock/examples/CodeBlockBasic.tsx new file mode 100644 index 00000000000..f0d07a4fe6d --- /dev/null +++ b/packages/react-core/src/components/CodeBlock/examples/CodeBlockBasic.tsx @@ -0,0 +1,73 @@ +import { Fragment, useState } from 'react'; +import { + CodeBlock, + CodeBlockAction, + CodeBlockCode, + ClipboardCopyButton, + Button, + Tooltip +} from '@patternfly/react-core'; +import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; + +export const BasicCodeBlock: React.FunctionComponent = () => { + const [copied, setCopied] = useState(false); + const [isRunning, setisRunning] = useState(false); + const runText: string = 'Run in web terminal'; + const doneRunText: string = 'Running in web terminal'; + + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const code = String.raw`apiVersion: helm.openshift.io/v1beta1/ +kind: HelmChartRepository +metadata: +name: azure-sample-repo0oooo00ooo +spec: +connectionConfig: +url: https://raw.githubusercontent.com/Azure-Samples/helm-charts/master/docs`; + + const actions = ( + + + onClick(e, code)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied ? 'Successfully copied to clipboard!' : 'Copy to clipboard'} + + + + setisRunning(false)} + > +
    + ); +}; + +CompassNavHome.displayName = 'CompassNavHome'; diff --git a/packages/react-core/src/components/Compass/CompassNavMain.tsx b/packages/react-core/src/components/Compass/CompassNavMain.tsx new file mode 100644 index 00000000000..082e75c61e8 --- /dev/null +++ b/packages/react-core/src/components/Compass/CompassNavMain.tsx @@ -0,0 +1,21 @@ +import styles from '@patternfly/react-styles/css/components/Compass/compass'; +import { css } from '@patternfly/react-styles'; + +export interface CompassNavMainProps extends React.HTMLProps { + /** Content of the nav main section (typically tabs). */ + children: React.ReactNode; + /** Additional classes added to the nav main section. */ + className?: string; +} + +export const CompassNavMain: React.FunctionComponent = ({ + children, + className, + ...props +}: CompassNavMainProps) => ( +
    + {children} +
    +); + +CompassNavMain.displayName = 'CompassNavMain'; diff --git a/packages/react-core/src/components/Compass/CompassNavSearch.tsx b/packages/react-core/src/components/Compass/CompassNavSearch.tsx new file mode 100644 index 00000000000..5731b45883c --- /dev/null +++ b/packages/react-core/src/components/Compass/CompassNavSearch.tsx @@ -0,0 +1,70 @@ +import { useRef } from 'react'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; +import { css } from '@patternfly/react-styles'; +import { Button } from '../Button'; +import { Tooltip } from '../Tooltip'; + +const CompassSearchIcon = () => ( + +); + +export interface CompassNavSearchProps extends Omit, 'onClick'> { + /** Content to display in the tooltip. Defaults to "Search". */ + tooltipContent?: React.ReactNode; + /** Click handler for the search button. */ + onClick?: React.MouseEventHandler; + /** Additional classes added to the nav search wrapper. */ + className?: string; + /** Accessible label for the nav search. */ + 'aria-label'?: string; +} + +export const CompassNavSearch: React.FunctionComponent = ({ + 'aria-label': ariaLabel = 'Search', + tooltipContent = 'Search', + className, + onClick, + ...props +}: CompassNavSearchProps) => { + const buttonRef = useRef(null); + + return ( +
    + +
    + ); +}; + +CompassNavSearch.displayName = 'CompassNavSearch'; diff --git a/packages/react-core/src/components/Compass/__tests__/Compass.test.tsx b/packages/react-core/src/components/Compass/__tests__/Compass.test.tsx new file mode 100644 index 00000000000..52f60bfec79 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/Compass.test.tsx @@ -0,0 +1,191 @@ +import { render, screen } from '@testing-library/react'; +import { Compass } from '../Compass'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-compass').firstChild).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(); + expect(screen.getByTestId('compass')).toHaveClass('custom-class'); +}); + +test('Renders with default compass class', () => { + render(); + expect(screen.getByTestId('compass')).toHaveClass(styles.compass); +}); + +test('Renders header content when provided', () => { + render(Header content
    } />); + expect(screen.getByText('Header content')).toBeVisible(); +}); + +test('Renders sidebar start content when provided', () => { + render(Sidebar start
    } />); + expect(screen.getByText('Sidebar start')).toBeVisible(); +}); + +test('Renders main content when provided', () => { + render(Main content
    } />); + expect(screen.getByText('Main content')).toBeVisible(); +}); + +test('Renders sidebar end content when provided', () => { + render(Sidebar end
    } />); + expect(screen.getByText('Sidebar end')).toBeVisible(); +}); + +test('Renders footer content when provided', () => { + render(Footer content
    } />); + expect(screen.getByText('Footer content')).toBeVisible(); +}); + +test('Renders header with expanded class when isHeaderExpanded is true', () => { + render(Header
    } isHeaderExpanded />); + expect(screen.getByText('Header').parentElement).toHaveClass('pf-m-expanded'); +}); + +test('Renders header without expanded class and with inert when isHeaderExpanded is false', () => { + render(Header
    } isHeaderExpanded={false} />); + const headerElement = screen.getByText('Header').parentElement; + expect(headerElement).not.toHaveClass('pf-m-expanded'); + expect(headerElement).toHaveAttribute('inert'); +}); + +test('Renders sidebar start with expanded class when isSidebarStartExpanded is true', () => { + render(Sidebar start
    } isSidebarStartExpanded />); + expect(screen.getByText('Sidebar start').parentElement).toHaveClass('pf-m-expanded'); +}); + +test('Renders sidebar start without expanded class and with inert when isSidebarStartExpanded is false', () => { + render(Sidebar start
    } isSidebarStartExpanded={false} />); + const sidebarElement = screen.getByText('Sidebar start').parentElement; + expect(sidebarElement).not.toHaveClass('pf-m-expanded'); + expect(sidebarElement).toHaveAttribute('inert'); +}); + +test('Renders sidebar end with expanded class when isSidebarEndExpanded is true', () => { + render(Sidebar end
    } isSidebarEndExpanded />); + expect(screen.getByText('Sidebar end').parentElement).toHaveClass('pf-m-expanded'); +}); + +test('Renders sidebar end without expanded class and with inert when isSidebarEndExpanded is false', () => { + render(Sidebar end
    } isSidebarEndExpanded={false} />); + const sidebarElement = screen.getByText('Sidebar end').parentElement; + expect(sidebarElement).not.toHaveClass('pf-m-expanded'); + expect(sidebarElement).toHaveAttribute('inert'); +}); + +test('Renders footer with expanded class when isFooterExpanded is true', () => { + render(Footer
    } isFooterExpanded />); + expect(screen.getByText('Footer').parentElement).toHaveClass('pf-m-expanded'); +}); + +test('Renders footer without expanded class and with inert when isFooterExpanded is false', () => { + render(Footer
    } isFooterExpanded={false} />); + const footerElement = screen.getByText('Footer').parentElement; + expect(footerElement).not.toHaveClass('pf-m-expanded'); + expect(footerElement).toHaveAttribute('inert'); +}); + +test('Renders with drawer when drawerContent is provided', () => { + render(Drawer content
    } />); + expect(screen.getByText('Drawer content')).toBeVisible(); +}); + +test('Renders with additional props spread to the component', () => { + render(); + expect(screen.getByTestId('compass')).toHaveAccessibleName('Test label'); +}); + +test('Renders with default expansion states', () => { + render( + Header
    } + sidebarStart={
    Sidebar start
    } + sidebarEnd={
    Sidebar end
    } + footer={
    Footer
    } + > + Test + + ); + + expect(screen.getByText('Header').parentElement).toHaveClass('pf-m-expanded'); + expect(screen.getByText('Sidebar start').parentElement).toHaveClass('pf-m-expanded'); + expect(screen.getByText('Sidebar end').parentElement).toHaveClass('pf-m-expanded'); + expect(screen.getByText('Footer').parentElement).toHaveClass('pf-m-expanded'); +}); + +test('Matches the snapshot with basic layout', () => { + const { asFragment } = render( + Header
    } + sidebarStart={
    Sidebar start
    } + main={
    Main content
    } + sidebarEnd={
    Sidebar end
    } + footer={
    Footer
    } + /> + ); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Matches the snapshot with drawer', () => { + const { asFragment } = render( + Drawer content
    } + drawerProps={{ isExpanded: true }} + header={
    Header
    } + sidebarStart={
    Sidebar start
    } + main={
    Main content
    } + sidebarEnd={
    Sidebar end
    } + footer={
    Footer
    } + /> + ); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with ${styles.modifiers.docked} class when dock is passed`, () => { + render(Dock content
    } data-testid="compass" />); + expect(screen.getByTestId('compass')).toHaveClass(styles.modifiers.docked); +}); + +test(`Does not render with ${styles.modifiers.docked} class when dock is not passed`, () => { + render(); + expect(screen.getByTestId('compass')).not.toHaveClass(styles.modifiers.docked); +}); + +test('Does not render masthead content when dock is not passed', () => { + render(); + expect(screen.queryByText('Masthead content')).not.toBeInTheDocument(); +}); + +test('Renders masthead content when dock is passed', () => { + render(Masthead content
    } dock={
    Dock content
    } />); + expect(screen.getByText('Masthead content')).toBeVisible(); +}); + +test(`Renders dock with ${styles.modifiers.expanded} class when isDockExpanded is true`, () => { + render(); + expect(screen.getByText('Dock content')).toHaveClass(styles.modifiers.expanded); +}); + +test(`Renders dock without ${styles.modifiers.expanded} class when isDockExpanded is false`, () => { + render(); + expect(screen.getByText('Dock content')).not.toHaveClass(styles.modifiers.expanded); +}); + +test(`Renders dock with ${styles.modifiers.textExpanded} class when isDockTextExpanded is true`, () => { + render(); + expect(screen.getByText('Dock content')).toHaveClass(styles.modifiers.textExpanded); +}); + +test(`Renders dock without ${styles.modifiers.textExpanded} class when isDockTextExpanded is false`, () => { + render(); + expect(screen.getByText('Dock content')).not.toHaveClass(styles.modifiers.textExpanded); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassContent.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassContent.test.tsx new file mode 100644 index 00000000000..1b3cf2eeb0f --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassContent.test.tsx @@ -0,0 +1,46 @@ +import { render, screen } from '@testing-library/react'; +import { CompassContent } from '../CompassContent'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassContent} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassContent); +}); + +test('Renders with drawer when drawerContent is provided', () => { + render(Drawer content
    }>Test); + expect(screen.getByText('Drawer content')).toBeVisible(); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot without drawer', () => { + const { asFragment } = render( + +
    Test content
    +
    + ); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Matches the snapshot with drawer', () => { + const { asFragment } = render( + Drawer content
    } drawerProps={{ isExpanded: true }}> +
    Test content
    + + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassDockMain.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassDockMain.test.tsx new file mode 100644 index 00000000000..18798a0b020 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassDockMain.test.tsx @@ -0,0 +1,41 @@ +import { render, screen } from '@testing-library/react'; +import { CompassDockMain } from '../CompassDockMain'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-compass-dock-main').firstChild).toBeVisible(); +}); + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassDockMain} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassDockMain, { exact: true }); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAttribute('id', 'custom-id'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
    Test content
    +
    + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassHeader.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassHeader.test.tsx new file mode 100644 index 00000000000..750f275671d --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassHeader.test.tsx @@ -0,0 +1,56 @@ +import { render, screen } from '@testing-library/react'; +import { CompassHeader } from '../CompassHeader'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-header').firstChild).toBeVisible(); +}); + +test('Renders logo content when provided', () => { + render(Logo content
    } />); + expect(screen.getByText('Logo content')).toBeVisible(); +}); + +test('Renders nav content when provided', () => { + render(Nav content
    } />); + expect(screen.getByText('Nav content')).toBeVisible(); +}); + +test('Renders profile content when provided', () => { + render(Profile content
    } />); + expect(screen.getByText('Profile content')).toBeVisible(); +}); + +test('Renders all content when all props are provided', () => { + render(Logo
    } nav={
    Nav
    } profile={
    Profile
    } />); + expect(screen.getByText('Logo')).toBeVisible(); + expect(screen.getByText('Nav')).toBeVisible(); + expect(screen.getByText('Profile')).toBeVisible(); +}); + +test(`Renders logo with ${styles.compass}__logo class`, () => { + render(Logo
    } />); + expect(screen.getByText('Logo').parentElement).toHaveClass(`${styles.compass}__logo`); +}); + +test(`Renders nav with ${styles.compassNav} class`, () => { + render(Nav
    } />); + expect(screen.getByText('Nav').parentElement).toHaveClass(styles.compassNav); +}); + +test(`Renders profile with ${styles.compassProfile} class`, () => { + render(Profile
    } />); + expect(screen.getByText('Profile').parentElement).toHaveClass(styles.compassProfile); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + Logo
    } nav={
    Nav
    } profile={
    Profile
    } /> + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassHero.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassHero.test.tsx new file mode 100644 index 00000000000..c46f8605e73 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassHero.test.tsx @@ -0,0 +1,38 @@ +import { render, screen } from '@testing-library/react'; +import { CompassHero } from '../CompassHero'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-hero').firstChild).toBeVisible(); +}); + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test(`Renders with ${styles.compass}__hero class by defaulty`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(`${styles.compass}__hero`, { exact: true }); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Hero content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassMainFooter.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassMainFooter.test.tsx new file mode 100644 index 00000000000..25b955ba77c --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassMainFooter.test.tsx @@ -0,0 +1,52 @@ +import { render, screen } from '@testing-library/react'; +import { CompassMainFooter } from '../CompassMainFooter'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-main-footer').firstChild).toBeVisible(); +}); + +test('Renders with children', () => { + render(Custom content); + expect(screen.getByText('Custom content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassMainFooter} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassMainFooter); +}); + +test(`Renders with pf-m-expanded class by default`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-expanded'); +}); + +test(`Renders with pf-m-expanded class when isExpanded is true`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-expanded'); +}); + +test(`Renders without pf-m-expanded class when isExpanded is false`, () => { + render(Test); + expect(screen.getByText('Test')).not.toHaveClass('pf-m-expanded'); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Custom children content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassMainHeader.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassMainHeader.test.tsx new file mode 100644 index 00000000000..ef2b630edac --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassMainHeader.test.tsx @@ -0,0 +1,130 @@ +import { render, screen } from '@testing-library/react'; +import { CompassMainHeader } from '../CompassMainHeader'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; +import panelStyles from '@patternfly/react-styles/css/components/Panel/panel'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-main-header').firstChild).toBeVisible(); +}); + +test('Renders with children', () => { + render(Custom content); + expect(screen.getByText('Custom content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compass}__main-header class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(`${styles.compass}__main-header`); +}); + +test('Renders title when provided', () => { + render(Title content}>Test); + expect(screen.getByText('Title content')).toBeVisible(); +}); + +test('Renders toolbar when provided', () => { + render(Toolbar content}>Test); + expect(screen.getByText('Toolbar content')).toBeVisible(); +}); + +test('Renders both title and toolbar when provided', () => { + render( + Title} toolbar={
    Toolbar
    }> + Test +
    + ); + expect(screen.getByText('Title')).toBeVisible(); + expect(screen.getByText('Toolbar')).toBeVisible(); +}); + +test('Ignores children when title is provided', () => { + render(Title}>Ignored children); + expect(screen.getByText('Title')).toBeVisible(); + expect(screen.queryByText('Ignored children')).not.toBeInTheDocument(); +}); + +test('Ignores children when toolbar is provided', () => { + render(Toolbar}>Ignored children); + expect(screen.getByText('Toolbar')).toBeVisible(); + expect(screen.queryByText('Ignored children')).not.toBeInTheDocument(); +}); + +test('Ignores children when both title and toolbar are provided', () => { + render( + Title} toolbar={
    Toolbar
    }> + Ignored children +
    + ); + expect(screen.getByText('Title')).toBeVisible(); + expect(screen.getByText('Toolbar')).toBeVisible(); + expect(screen.queryByText('Ignored children')).not.toBeInTheDocument(); +}); + +test('Renders children when neither title nor toolbar are provided', () => { + render(Custom children content); + expect(screen.getByText('Custom children content')).toBeVisible(); +}); + +test('Renders Panel when title is passed', () => { + render(); + + const panel = screen.getByTestId('test-id').firstChild; + expect(panel).toHaveClass(panelStyles.panel); +}); + +test('Renders Panel when toolbar is passed', () => { + render(); + + const panel = screen.getByTestId('test-id').firstChild; + expect(panel).toHaveClass(panelStyles.panel); +}); + +test('Does not render Panel when children are passed', () => { + render( + +
    Children content
    +
    + ); + + const content = screen.getByTestId('test-id').firstChild; + expect(content).not.toHaveClass(panelStyles.panel); +}); + +test('Passes props to Panel when title and panelProps is passed', () => { + render(); + + const panel = screen.getByTestId('test-id').firstChild; + expect(panel).toHaveClass('panel-class'); +}); + +test('Passes props to Panel when toolbar and panelProps is passed', () => { + render(); + + const panel = screen.getByTestId('test-id').firstChild; + expect(panel).toHaveClass('panel-class'); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAttribute('id', 'custom-id'); +}); + +test('Matches the snapshot with both title and toolbar', () => { + const { asFragment } = render(Title} toolbar={
    Toolbar
    } />); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Matches the snapshot with children', () => { + const { asFragment } = render(Custom children content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderContent.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderContent.test.tsx new file mode 100644 index 00000000000..44475ae7dca --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderContent.test.tsx @@ -0,0 +1,28 @@ +import { render, screen } from '@testing-library/react'; +import { CompassMainHeaderContent } from '../CompassMainHeaderContent'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Custom content); + expect(screen.getByText('Custom content')).toBeVisible(); +}); + +test(`Renders with default ${styles.compass}__main-header-content class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(`${styles.compass}__main-header-content`); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAttribute('id', 'custom-id'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderTitle.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderTitle.test.tsx new file mode 100644 index 00000000000..9bc10b59b45 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderTitle.test.tsx @@ -0,0 +1,28 @@ +import { render, screen } from '@testing-library/react'; +import { CompassMainHeaderTitle } from '../CompassMainHeaderTitle'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Custom content); + expect(screen.getByText('Custom content')).toBeVisible(); +}); + +test(`Renders with default ${styles.compass}__main-header-title class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(`${styles.compass}__main-header-title`); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAttribute('id', 'custom-id'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderToolbar.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderToolbar.test.tsx new file mode 100644 index 00000000000..62ab818f602 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassMainHeaderToolbar.test.tsx @@ -0,0 +1,28 @@ +import { render, screen } from '@testing-library/react'; +import { CompassMainHeaderToolbar } from '../CompassMainHeaderToolbar'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Custom content); + expect(screen.getByText('Custom content')).toBeVisible(); +}); + +test(`Renders with default ${styles.compass}__main-header-toolbar class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(`${styles.compass}__main-header-toolbar`); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAttribute('id', 'custom-id'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassMessageBar.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassMessageBar.test.tsx new file mode 100644 index 00000000000..f6f7546e72c --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassMessageBar.test.tsx @@ -0,0 +1,41 @@ +import { render, screen } from '@testing-library/react'; +import { CompassMessageBar } from '../CompassMessageBar'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-message-bar').firstChild).toBeVisible(); +}); + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassMessageBar} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassMessageBar); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
    Message bar content
    +
    + ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavContent.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavContent.test.tsx new file mode 100644 index 00000000000..eb176b5ccae --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavContent.test.tsx @@ -0,0 +1,37 @@ +import { render, screen } from '@testing-library/react'; +import { CompassNavContent } from '../CompassNavContent'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Test content); + + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassNavContent} class`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.compassNavContent, { exact: true }); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
    Nav content wrapper
    +
    + ); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavHome.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavHome.test.tsx new file mode 100644 index 00000000000..2f3b8b6fed1 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavHome.test.tsx @@ -0,0 +1,89 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { CompassNavHome } from '../CompassNavHome'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with default aria-label', () => { + render(); + + expect(screen.getByRole('button', { name: 'Home' })).toBeVisible(); +}); + +test('Renders with custom aria-label when provided', () => { + render(); + + expect(screen.getByRole('button', { name: 'Custom home' })).toBeVisible(); +}); + +test('Renders with default tooltip content', async () => { + const user = userEvent.setup(); + + render(); + + const button = screen.getByRole('button'); + + await user.hover(button); + + await screen.findByRole('tooltip'); + + expect(screen.getByRole('tooltip')).toHaveTextContent('Home'); +}); + +test('Renders with custom tooltip content when provided', async () => { + const user = userEvent.setup(); + + render(); + + const button = screen.getByRole('button'); + + await user.hover(button); + + await screen.findByRole('tooltip'); + expect(screen.getByRole('tooltip')).toHaveTextContent('Custom tooltip'); +}); + +test('Renders with custom class name when className prop is provided', () => { + const { container } = render(); + + expect(container.firstChild).toHaveClass('custom-class'); +}); + +test(`Renders with default class`, () => { + const { container } = render(); + + expect(container.firstChild).toHaveClass(styles.compassNav + '-home', { exact: true }); +}); + +test('Calls onClick handler when button is clicked', async () => { + const user = userEvent.setup(); + const onClick = jest.fn(); + + render(); + + await user.click(screen.getByRole('button', { name: 'Home' })); + + expect(onClick).toHaveBeenCalledTimes(1); +}); + +test('Renders button with plain variant and circle shape', () => { + render(); + + const button = screen.getByRole('button', { name: 'Home' }); + + expect(button).toHaveClass('pf-m-plain'); + expect(button).toHaveClass('pf-m-circle'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(); + + expect(asFragment()).toMatchSnapshot(); +}); + +test('Matches the snapshot with custom props', () => { + const { asFragment } = render( + + ); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavMain.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavMain.test.tsx new file mode 100644 index 00000000000..0242f9ef64c --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavMain.test.tsx @@ -0,0 +1,37 @@ +import { render, screen } from '@testing-library/react'; +import { CompassNavMain } from '../CompassNavMain'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Test content); + + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassNavMain} class`, () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass(styles.compassNavMain, { exact: true }); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
    Main tabs content
    +
    + ); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavSearch.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavSearch.test.tsx new file mode 100644 index 00000000000..a32111d6899 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavSearch.test.tsx @@ -0,0 +1,87 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { CompassNavSearch } from '../CompassNavSearch'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with default aria-label', () => { + render(); + expect(screen.getByRole('button', { name: 'Search' })).toBeVisible(); +}); + +test('Renders with custom aria-label when provided', () => { + render(); + expect(screen.getByRole('button', { name: 'Custom search' })).toBeVisible(); +}); + +test('Renders with default tooltip content', async () => { + const user = userEvent.setup(); + + render(); + + const button = screen.getByRole('button'); + + await user.hover(button); + + await screen.findByRole('tooltip'); + + expect(screen.getByRole('tooltip')).toHaveTextContent('Search'); +}); + +test('Renders with custom tooltip content when provided', async () => { + const user = userEvent.setup(); + + render(); + + const button = screen.getByRole('button'); + + await user.hover(button); + + await screen.findByRole('tooltip'); + + expect(screen.getByRole('tooltip')).toHaveTextContent('Custom tooltip'); +}); + +test('Renders with custom class name when className prop is provided', () => { + const { container } = render(); + + expect(container.firstChild).toHaveClass('custom-class'); +}); + +test(`Renders with default class`, () => { + const { container } = render(); + + expect(container.firstChild).toHaveClass(styles.compassNav + '-search', { exact: true }); +}); + +test('Calls onClick handler when button is clicked', async () => { + const user = userEvent.setup(); + const onClick = jest.fn(); + + render(); + + await user.click(screen.getByRole('button', { name: 'Search' })); + + expect(onClick).toHaveBeenCalledTimes(1); +}); + +test('Renders button with plain variant and circle shape', () => { + render(); + + const button = screen.getByRole('button', { name: 'Search' }); + + expect(button).toHaveClass('pf-m-plain'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(); + + expect(asFragment()).toMatchSnapshot(); +}); + +test('Matches the snapshot with custom props', () => { + const { asFragment } = render( + + ); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/Compass.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/Compass.test.tsx.snap new file mode 100644 index 00000000000..ceaae419241 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/Compass.test.tsx.snap @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot with basic layout 1`] = ` + +
    +
    +
    +
    + Header +
    +
    +
    +
    + Sidebar start +
    +
    +
    +
    + Main content +
    +
    +
    +
    + Sidebar end +
    +
    + +
    +
    +
    +`; + +exports[`Matches the snapshot with drawer 1`] = ` + +
    +
    +
    +
    +
    +
    +
    +
    + Header +
    +
    +
    +
    + Sidebar start +
    +
    +
    +
    + Main content +
    +
    +
    +
    + Sidebar end +
    +
    + +
    +
    +
    +
    + Drawer content +
    +
    +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassContent.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassContent.test.tsx.snap new file mode 100644 index 00000000000..c0dae790afa --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassContent.test.tsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot with drawer 1`] = ` + +
    +
    +
    +
    +
    + Test content +
    +
    +
    +
    + Drawer content +
    +
    +
    +
    +`; + +exports[`Matches the snapshot without drawer 1`] = ` + +
    +
    + Test content +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassDockMain.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassDockMain.test.tsx.snap new file mode 100644 index 00000000000..b9198688601 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassDockMain.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    +
    + Test content +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassHeader.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassHeader.test.tsx.snap new file mode 100644 index 00000000000..f3e52b6d77d --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassHeader.test.tsx.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + + +
    +
    + Nav +
    +
    +
    +
    + Profile +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassHero.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassHero.test.tsx.snap new file mode 100644 index 00000000000..da16b2c6089 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassHero.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + Hero content +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainFooter.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainFooter.test.tsx.snap new file mode 100644 index 00000000000..160ef4650a2 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainFooter.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + + + +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeader.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeader.test.tsx.snap new file mode 100644 index 00000000000..e674266cf33 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeader.test.tsx.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot with both title and toolbar 1`] = ` + +
    +
    +
    +
    +
    +
    +
    + Title +
    +
    +
    +
    + Toolbar +
    +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`Matches the snapshot with children 1`] = ` + +
    + Custom children content +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderContent.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderContent.test.tsx.snap new file mode 100644 index 00000000000..c49e1a1d468 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderContent.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + Content +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderTitle.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderTitle.test.tsx.snap new file mode 100644 index 00000000000..15ac7ab71eb --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderTitle.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + Content +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderToolbar.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderToolbar.test.tsx.snap new file mode 100644 index 00000000000..79550ac0b48 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMainHeaderToolbar.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + Content +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMessageBar.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMessageBar.test.tsx.snap new file mode 100644 index 00000000000..edde4c73946 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassMessageBar.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    +
    + Message bar content +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavContent.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavContent.test.tsx.snap new file mode 100644 index 00000000000..df1e9a2ddea --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavContent.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    +
    + Nav content wrapper +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavHome.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavHome.test.tsx.snap new file mode 100644 index 00000000000..96703d6ebaa --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavHome.test.tsx.snap @@ -0,0 +1,107 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + +
    +
    +`; + +exports[`Matches the snapshot with custom props 1`] = ` + +
    + +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavMain.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavMain.test.tsx.snap new file mode 100644 index 00000000000..53987fbf559 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavMain.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    +
    + Main tabs content +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavSearch.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavSearch.test.tsx.snap new file mode 100644 index 00000000000..c6e1a8b4953 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavSearch.test.tsx.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + + + +`; + +exports[`Matches the snapshot with custom props 1`] = ` + + + +`; diff --git a/packages/react-core/src/components/Compass/examples/Compass.md b/packages/react-core/src/components/Compass/examples/Compass.md new file mode 100644 index 00000000000..c10254b59f7 --- /dev/null +++ b/packages/react-core/src/components/Compass/examples/Compass.md @@ -0,0 +1,78 @@ +--- +id: Compass +cssPrefix: pf-v6-c-compass +section: components +beta: true +propComponents: + [ + 'Compass', + 'CompassHeader', + 'CompassContent', + 'CompassHero', + 'CompassMainHeader', + 'CompassMessageBar', + 'CompassMainFooter' + ] +--- + +import { useRef, useState, useEffect } from 'react'; +import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; +import OutlinedPlusSquare from '@patternfly/react-icons/dist/esm/icons/outlined-plus-square-icon'; +import OutlinedCopy from '@patternfly/react-icons/dist/esm/icons/outlined-copy-icon'; +import RhUiQuestionMarkCircleIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-question-mark-circle-icon'; + +import './compass.css'; + +## Examples + +### Basic + +In a basic Compass layout, content can be passed to the following props to populate different areas of the page: + +- `header`: Content rendered at the top of the page, typically including a `` component that divides the header into 3 areas, with a logo or brand, middle navigation, and profile. +- `sidebarStart`: Content rendered at the horizontal start of the page (by default, the left side). +- `main`: Content rendered in the center of the page, typically including a `` or ``, along with a `` filled with 1 or more `` components. +- `sidebarEnd`: Content rendered at the horizontal end of the page (by default, the right side). +- `footer`: Content rendered at the bottom of the page. + +The background image of `` is set at a global level alongside the theme. You can customize the background image of the `` inside `` by using its `backgroundSrcLight` and `backgroundSrcDark` props, or you may set a gradient using the `gradientLight` and `gradientDark` props. + +```ts isBeta file="CompassBasic.tsx" + +``` + +### With alternate footer + +When `footer` is used, its content will fill the width of the screen. By default, when content inside the footer grows, the height and placement of the start and end sidebars will adjust to allow for the change. To modify this behavior and render footer content without interfering with the sidebars, instead place a `` inside the `main` section. This will render content at the bottom of the page between the 2 sidebars, rather than across the entire bottom of the page. + +```ts file="CompassMainFooterDemo.tsx" + +``` + +### With docked nav + +```ts file="CompassDockLayout.tsx" + +``` + +## Composable structure + +When building a more custom implementation with Compass components, there are some intended or expected structures that must remain present. + +### CompassMainHeader structure + +When using the `children` property in the `` component, there are specific structural patterns that you should follow, as shown this general code structure. + +```noLive + + + + + + {Your custom content goes here, which can include the and/or sub-components} + + + + + +``` diff --git a/packages/react-core/src/components/Compass/examples/CompassBasic.tsx b/packages/react-core/src/components/Compass/examples/CompassBasic.tsx new file mode 100644 index 00000000000..d6ea4b184dd --- /dev/null +++ b/packages/react-core/src/components/Compass/examples/CompassBasic.tsx @@ -0,0 +1,52 @@ +import { + Compass, + CompassHeader, + CompassHero, + CompassContent, + CompassMainHeader, + Panel, + PanelMain, + PanelMainBody, + CompassMainHeaderContent +} from '@patternfly/react-core'; +import './compass.css'; + +export const CompassBasic: React.FunctionComponent = () => { + const headerContent = Logo} nav={
    Nav
    } profile={
    Profile
    } />; + const sidebarStartContent =
    Sidebar start
    ; + // TODO: simplify mainContent to only a div string + const mainContent = ( + <> + +
    Hero
    +
    + + + + + + +
    Content title
    +
    +
    +
    +
    +
    +
    Content
    +
    + + ); + const sidebarEndContent =
    Sidebar end
    ; + const footerContent =
    Footer
    ; + + return ( + + ); +}; diff --git a/packages/react-core/src/components/Compass/examples/CompassDockLayout.tsx b/packages/react-core/src/components/Compass/examples/CompassDockLayout.tsx new file mode 100644 index 00000000000..09cf87dc5f7 --- /dev/null +++ b/packages/react-core/src/components/Compass/examples/CompassDockLayout.tsx @@ -0,0 +1,31 @@ +import { + Compass, + CompassContent, + CompassMainHeader, + Panel, + PanelMain, + PanelMainBody, + CompassMainHeaderContent +} from '@patternfly/react-core'; +import './compass.css'; + +export const CompassBasic: React.FunctionComponent = () => { + const dockContent =
    Content
    ; + const mainContent = ( + + + + + + +
    Content title
    +
    +
    +
    +
    +
    +
    Content
    +
    + ); + return ; +}; diff --git a/packages/react-core/src/components/Compass/examples/CompassMainFooterDemo.tsx b/packages/react-core/src/components/Compass/examples/CompassMainFooterDemo.tsx new file mode 100644 index 00000000000..4846f6f07aa --- /dev/null +++ b/packages/react-core/src/components/Compass/examples/CompassMainFooterDemo.tsx @@ -0,0 +1,43 @@ +import { + Compass, + CompassHeader, + CompassHero, + CompassContent, + CompassMainHeader, + CompassMainFooter +} from '@patternfly/react-core'; +import './compass.css'; + +export const CompassMainFooterDemo: React.FunctionComponent = () => { + const headerContent = Logo} nav={
    Nav
    } profile={
    Profile
    } />; + const sidebarStartContent =
    Sidebar start
    ; + // TODO: simplify mainContent to only a div string + const mainContent = ( + <> + +
    Hero
    +
    + + +
    Content title
    +
    +
    Content
    +
    + +
    Footer
    +
    + + ); + const sidebarEndContent =
    Sidebar end
    ; + + return ( + + ); +}; diff --git a/packages/react-core/src/components/Compass/examples/compass.css b/packages/react-core/src/components/Compass/examples/compass.css new file mode 100644 index 00000000000..8a1d76248e3 --- /dev/null +++ b/packages/react-core/src/components/Compass/examples/compass.css @@ -0,0 +1,35 @@ +#ws-react-c-compass-basic [class*="pf-v6-c-compass"] { + position: relative; +} + +#ws-react-c-compass-basic [class*="pf-v6-c-compass"]::after { + content: ""; + position: absolute; + inset: 0; + border: var(--pf-t--global--border--width--regular) dashed var(--pf-t--global--border--color--default); + pointer-events: none; +} + +#ws-react-c-compass-with-alternate-footer [class*="pf-v6-c-compass"] { + position: relative; +} + +#ws-react-c-compass-with-alternate-footer [class*="pf-v6-c-compass"]:not([class*="footer"])::after { + content: ""; + position: absolute; + inset: 0; + border: var(--pf-t--global--border--width--regular) dashed var(--pf-t--global--border--color--default); + pointer-events: none; +} + +#ws-react-c-compass-with-docked-nav [class*="pf-v6-c-compass"] { + position: relative; +} + +#ws-react-c-compass-with-docked-nav [class*="pf-v6-c-compass"]:not([class*="footer"])::after { + content: ""; + position: absolute; + inset: 0; + border: var(--pf-t--global--border--width--regular) dashed var(--pf-t--global--border--color--default); + pointer-events: none; +} diff --git a/packages/react-core/src/components/Compass/index.ts b/packages/react-core/src/components/Compass/index.ts new file mode 100644 index 00000000000..c229910c584 --- /dev/null +++ b/packages/react-core/src/components/Compass/index.ts @@ -0,0 +1,15 @@ +export * from './Compass'; +export * from './CompassContent'; +export * from './CompassDockMain'; +export * from './CompassHeader'; +export * from './CompassHero'; +export * from './CompassMainHeader'; +export * from './CompassMainHeaderContent'; +export * from './CompassMainHeaderTitle'; +export * from './CompassMainHeaderToolbar'; +export * from './CompassMainFooter'; +export * from './CompassMessageBar'; +export * from './CompassNavContent'; +export * from './CompassNavHome'; +export * from './CompassNavMain'; +export * from './CompassNavSearch'; diff --git a/packages/react-core/src/components/Content/Content.tsx b/packages/react-core/src/components/Content/Content.tsx new file mode 100644 index 00000000000..896f6a040ed --- /dev/null +++ b/packages/react-core/src/components/Content/Content.tsx @@ -0,0 +1,119 @@ +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Content/content'; +import { useOUIAProps, OUIAProps } from '../../helpers'; + +export enum ContentVariants { + h1 = 'h1', + h2 = 'h2', + h3 = 'h3', + h4 = 'h4', + h5 = 'h5', + h6 = 'h6', + p = 'p', + a = 'a', + small = 'small', + blockquote = 'blockquote', + pre = 'pre', + hr = 'hr', + ul = 'ul', + ol = 'ol', + dl = 'dl', + li = 'li', + dt = 'dt', + dd = 'dd' +} + +export interface ContentProps extends React.HTMLProps, OUIAProps { + /** The content component. If none provided, it will be a 'div' and styling will be applied to all its child components. */ + component?: + | 'h1' + | 'h2' + | 'h3' + | 'h4' + | 'h5' + | 'h6' + | 'p' + | 'a' + | 'small' + | 'blockquote' + | 'pre' + | 'hr' + | 'ul' + | 'ol' + | 'dl' + | 'li' + | 'dt' + | 'dd'; + /** Children rendered within the Content. */ + children?: React.ReactNode; + /** Additional classes added to the Content. */ + className?: string; + /** Modifies the list (ul, ol and dl components) to have plain styling. */ + isPlainList?: boolean; + /** Flag to indicate the link (or all links within the content) has visited styles applied if the browser determines the link has been visited. */ + isVisitedLink?: boolean; + /** Flag to indicate the content has editorial styling. This styling increases the font size of body text and small text by one tier, increasing body text to large and small text to the previous body text size. */ + isEditorial?: boolean; + /** Value to overwrite the randomly generated data-ouia-component-id. */ + ouiaId?: number | string; + /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ + ouiaSafe?: boolean; +} + +const componentStyles = { + div: styles.content, + h1: styles.contentH1, + h2: styles.contentH2, + h3: styles.contentH3, + h4: styles.contentH4, + h5: styles.contentH5, + h6: styles.contentH6, + p: styles.contentP, + a: styles.contentA, + small: styles.contentSmall, + blockquote: styles.contentBlockquote, + pre: styles.contentPre, + hr: styles.contentHr, + ul: styles.contentUl, + ol: styles.contentOl, + dl: styles.contentDl, + li: styles.contentLi, + dt: styles.contentDt, + dd: styles.contentDd +}; + +export const Content: React.FunctionComponent = ({ + children, + className = '', + component, + isPlainList = false, + isVisitedLink = false, + ouiaId, + ouiaSafe = true, + isEditorial = false, + ...props +}: ContentProps) => { + const wrappingComponent = component ?? 'div'; + const Component: any = wrappingComponent; + const ouiaProps = useOUIAProps(Content.displayName, ouiaId, ouiaSafe); + + const isList = ['ul', 'ol', 'dl'].includes(wrappingComponent); + + return ( + + {children} + + ); +}; +Content.displayName = 'Content'; diff --git a/packages/react-core/src/components/Content/__tests__/Content.test.tsx b/packages/react-core/src/components/Content/__tests__/Content.test.tsx new file mode 100644 index 00000000000..445f7c1b49a --- /dev/null +++ b/packages/react-core/src/components/Content/__tests__/Content.test.tsx @@ -0,0 +1,293 @@ +import { render, screen } from '@testing-library/react'; +import { Content } from '../Content'; +import styles from '@patternfly/react-styles/css/components/Content/content'; + +test('Renders without children', () => { + render( +
    + +
    + ); + expect(screen.getByTestId('test-content').firstChild).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + expect(screen.getByText('Test')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test('Renders as "div" element by default', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'DIV'); +}); + +test('Renders as "h1" element when component="h1"', () => { + render(Test); + expect(screen.getByRole('heading', { level: 1 })).toBeVisible(); +}); + +test('Renders as "h2" element when component="h2"', () => { + render(Test); + expect(screen.getByRole('heading', { level: 2 })).toBeVisible(); +}); + +test('Renders as "h3" element when component="h3"', () => { + render(Test); + expect(screen.getByRole('heading', { level: 3 })).toBeVisible(); +}); + +test('Renders as "h4" element when component="h4"', () => { + render(Test); + expect(screen.getByRole('heading', { level: 4 })).toBeVisible(); +}); + +test('Renders as "h5" element when component="h5"', () => { + render(Test); + expect(screen.getByRole('heading', { level: 5 })).toBeVisible(); +}); + +test('Renders as "h6" element when component="h6"', () => { + render(Test); + expect(screen.getByRole('heading', { level: 6 })).toBeVisible(); +}); + +test('Renders as "a" element when component="a"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'A'); +}); + +test('Renders as "blockquote" element when component="blockquote"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'BLOCKQUOTE'); +}); + +test('Renders as "pre" element when component="pre"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'PRE'); +}); + +test('Renders as "hr" element when component="hr"', () => { + render(); + expect(screen.getByRole('separator')).toHaveProperty('nodeName', 'HR'); +}); + +test('Renders as "ul" element component="ul"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'UL'); +}); + +test('Renders as "ol" element when component="ol"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'OL'); +}); + +test('Renders as "dl" element when component="dl"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'DL'); +}); + +test('Renders as "li" element when component="li"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'LI'); +}); + +test('Renders as "dt" element when component="dt"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'DT'); +}); + +test('Renders as "dd" element when component="dd"', () => { + render(Test); + expect(screen.getByText('Test')).toHaveProperty('nodeName', 'DD'); +}); + +test(`Renders with class name ${styles.contentH1} when component="h1"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentH1); +}); + +test(`Renders with class name ${styles.contentH2} when component="h2"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentH2); +}); + +test(`Renders with class name ${styles.contentH3} when component="h3"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentH3); +}); + +test(`Renders with class name ${styles.contentH4} when component="h4"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentH4); +}); + +test(`Renders with class name ${styles.contentH5} when component="h5"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentH5); +}); + +test(`Renders with class name ${styles.contentH6} when component="h6"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentH6); +}); + +test(`Renders with class name ${styles.contentP} when component="p"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentP); +}); + +test(`Renders with class name ${styles.contentA} when component="a"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentA); +}); + +test(`Renders with class name ${styles.contentSmall} when component="small"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentSmall); +}); + +test(`Renders with class name ${styles.contentBlockquote} when component="blockquote"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentBlockquote); +}); + +test(`Renders with class name ${styles.contentPre} when component="pre"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentPre); +}); + +test(`Renders with class name ${styles.contentHr} when component="hr"`, () => { + render(); + expect(screen.getByRole('separator')).toHaveClass(styles.contentHr); +}); + +test(`Renders with class name ${styles.contentUl} when component="ul"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentUl); +}); + +test(`Renders with class name ${styles.contentOl} when component="ol"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentOl); +}); + +test(`Renders with class name ${styles.contentDl} when component="dl"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentDl); +}); + +test(`Renders with class name ${styles.contentLi} when component="li"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentLi); +}); + +test(`Renders with class name ${styles.contentDt} when component="dt"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentDt); +}); + +test(`Renders with class name ${styles.contentDd} when component="dd"`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.contentDd); +}); + +test(`Renders with class name ${styles.content} when no component prop is provided`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.content); +}); + +test(`Renders without class name ${styles.content} when component is provided`, () => { + render(Test); + expect(screen.getByText('Test')).not.toHaveClass(styles.content); +}); + +test(`Renders with class name pf-m-plain when isPlainList=true and component is 'ul', 'ol' or 'dl'`, () => { + render( + <> + + Test1 + + + Test2 + + + Test3 + + + ); + expect(screen.getByText('Test1')).toHaveClass('pf-m-plain'); + expect(screen.getByText('Test2')).toHaveClass('pf-m-plain'); + expect(screen.getByText('Test3')).toHaveClass('pf-m-plain'); +}); + +test(`Renders without class name pf-m-plain by default`, () => { + render(Test); + expect(screen.getByText('Test')).not.toHaveClass('pf-m-plain'); +}); + +test(`Renders without class name pf-m-plain when isPlainList=true, but component is not 'ul', 'ol' or 'dl'`, () => { + render( + + Test + + ); + expect(screen.getByText('Test')).not.toHaveClass('pf-m-plain'); +}); + +test('Renders without class name pf-m-visited by default', () => { + render(Test); + expect(screen.getByText('Test')).not.toHaveClass('pf-m-visited'); +}); + +test('Renders with class name pf-m-visited when isVisitedLink=true', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-visited'); +}); + +test('Renders with class name pf-m-visited when isVisitedLink=true and component="a"', () => { + render( + + Test + + ); + expect(screen.getByText('Test')).toHaveClass('pf-m-visited'); +}); + +test('Renders with inherited element props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test(`Renders without class name ${styles.modifiers.editorial} by default`, () => { + render(Test); + expect(screen.getByText('Test')).not.toHaveClass('pf-m-editorial'); +}); + +test(`Renders with class name ${styles.modifiers.editorial} when isEditorial = true`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('pf-m-editorial'); +}); + +test(`Renders with class name ${styles.modifiers.editorial} when isEditorial = true and component is specified`, () => { + render( + + Test + + ); + expect(screen.getByText('Test')).toHaveClass('pf-m-editorial'); +}); + +test(`Renders without class name ${styles.modifiers.editorial} when isEditorial = false`, () => { + render(Test); + expect(screen.getByText('Test')).not.toHaveClass('pf-m-editorial'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Content/__tests__/__snapshots__/Content.test.tsx.snap b/packages/react-core/src/components/Content/__tests__/__snapshots__/Content.test.tsx.snap new file mode 100644 index 00000000000..7abe54a6a73 --- /dev/null +++ b/packages/react-core/src/components/Content/__tests__/__snapshots__/Content.test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
    + Test +
    +
    +`; diff --git a/packages/react-core/src/components/Content/examples/Content.md b/packages/react-core/src/components/Content/examples/Content.md new file mode 100644 index 00000000000..db83b5eb615 --- /dev/null +++ b/packages/react-core/src/components/Content/examples/Content.md @@ -0,0 +1,72 @@ +--- +id: Content +section: components +cssPrefix: pf-v6-c-content +propComponents: ['Content', 'ContentVariants'] +--- + +The `` component allows you to establish a block of HTML content and apply simple, built-in styling. `` can be used for any element supported by the `component` property (including `h1` through `h6`, `hr`, `p`, `a`, `small`, `blockquote`, and `pre`). + +You cannot nest other components within ``, and doing so can cause styling overrides or other conflicts. Instead, you can use the `` component's properties to achieve the same results. + +For example, to create a level 1 heading, you should pass `component="h1"` to ``, instead of nesting a `` component within `<Content>`. Similarly, when you need to add a divider to a page, you should utilize the `hr` property of `<Content>` (which is styled as a divider), rather than using a separate `<Divider>` component. + +## Examples + +HTML elements wrapped by `<Content>` are styled by the content component. + +### Content as a wrapper + +```ts file="./ContentWrapper.tsx" + +``` + +### Headings + +```ts file="./ContentHeadings.tsx" + +``` + +### Body + +```ts file="./ContentBody.tsx" + +``` + +### Unordered list + +```ts file="./ContentUnorderedList.tsx" + +``` + +### Ordered list + +```ts file="./ContentOrderedList.tsx" + +``` + +### Plain list + +```ts file="./ContentPlainList.tsx" + +``` + +### Description list + +```ts file="./ContentDescriptionList.tsx" + +``` + +### Link and visited link + +```ts file="./ContentVisited.tsx" + +``` + +### Editorial content + +Editorial styling increases the font size of body text and small text by 1 tier, where body text becomes "lg" and small text becomes "md". To applying editorial styling, use `isEditorial`. + +```ts file="./ContentEditorial.tsx" + +``` diff --git a/packages/react-core/src/components/Content/examples/ContentBody.tsx b/packages/react-core/src/components/Content/examples/ContentBody.tsx new file mode 100644 index 00000000000..b239985220e --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentBody.tsx @@ -0,0 +1,25 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentBody: React.FunctionComponent = () => ( + <> + <Content component={ContentVariants.p}> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla accumsan, metus ultrices eleifend gravida, nulla + nunc varius lectus, nec rutrum justo nibh eu lectus. Ut vulputate semper dui. Fusce erat odio, sollicitudin vel + erat vel, interdum mattis neque. Sub works as well! + </Content> + <Content component={ContentVariants.p}> + Quisque ante lacus, malesuada ac auctor vitae, congue{' '} + <Content component={ContentVariants.a} href="#"> + non ante + </Content> + . Phasellus lacus ex, semper ac tortor nec, fringilla condimentum orci. Fusce eu rutrum tellus. + </Content> + <Content component={ContentVariants.blockquote}> + Ut venenatis, nisl scelerisque sollicitudin fermentum, quam libero hendrerit ipsum, ut blandit est tellus sit amet + turpis. + </Content> + <Content component={ContentVariants.small}> + Sometimes you need small text to display things like date created + </Content> + </> +); diff --git a/packages/react-core/src/components/Content/examples/ContentDescriptionList.tsx b/packages/react-core/src/components/Content/examples/ContentDescriptionList.tsx new file mode 100644 index 00000000000..0199d09df33 --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentDescriptionList.tsx @@ -0,0 +1,12 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentDescriptionList: React.FunctionComponent = () => ( + <Content component={ContentVariants.dl}> + <Content component={ContentVariants.dt}>Web</Content> + <Content component={ContentVariants.dd}>The part of the Internet that contains websites and web pages</Content> + <Content component={ContentVariants.dt}>HTML</Content> + <Content component={ContentVariants.dd}>A markup language for creating web pages</Content> + <Content component={ContentVariants.dt}>CSS</Content> + <Content component={ContentVariants.dd}>A technology to make HTML look better</Content> + </Content> +); diff --git a/packages/react-core/src/components/Content/examples/ContentEditorial.tsx b/packages/react-core/src/components/Content/examples/ContentEditorial.tsx new file mode 100644 index 00000000000..c1690072ca9 --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentEditorial.tsx @@ -0,0 +1,23 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentEditorial: React.FunctionComponent = () => ( + <> + <Content component={ContentVariants.h1} isEditorial> + Example of editorial content via components + </Content> + <Content component={ContentVariants.p} isEditorial> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla accumsan, metus ultrices eleifend gravida, nulla + nunc varius lectus, nec rutrum justo nibh eu lectus. Ut vulputate semper dui. Fusce erat odio, sollicitudin vel + erat vel, interdum mattis neque. Sub works as well! + </Content> + <br /> + <Content isEditorial> + <h1>Example of editorial content via wrapper</h1> + <p> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla accumsan, metus ultrices eleifend gravida, nulla + nunc varius lectus, nec rutrum justo nibh eu lectus. Ut vulputate semper dui. Fusce erat odio, sollicitudin vel + erat vel, interdum mattis neque. Sub works as well! + </p> + </Content> + </> +); diff --git a/packages/react-core/src/components/Content/examples/ContentHeadings.tsx b/packages/react-core/src/components/Content/examples/ContentHeadings.tsx new file mode 100644 index 00000000000..4cde33a667e --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentHeadings.tsx @@ -0,0 +1,12 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentHeadings: React.FunctionComponent = () => ( + <> + <Content component={ContentVariants.h1}>Hello World</Content> + <Content component={ContentVariants.h2}>Second level</Content> + <Content component={ContentVariants.h3}>Third level</Content> + <Content component={ContentVariants.h4}>Fourth level</Content> + <Content component={ContentVariants.h5}>Fifth level</Content> + <Content component={ContentVariants.h6}>Sixth level</Content> + </> +); diff --git a/packages/react-core/src/components/Content/examples/ContentOrderedList.tsx b/packages/react-core/src/components/Content/examples/ContentOrderedList.tsx new file mode 100644 index 00000000000..bdb4fd73eec --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentOrderedList.tsx @@ -0,0 +1,13 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentOrderedList: React.FunctionComponent = () => ( + <Content component={ContentVariants.ol}> + <Content component={ContentVariants.li}>Donec blandit a lorem id convallis.</Content> + <Content component={ContentVariants.li}>Cras gravida arcu at diam gravida gravida.</Content> + <Content component={ContentVariants.li}>Integer in volutpat libero.</Content> + <Content component={ContentVariants.li}>Donec a diam tellus.</Content> + <Content component={ContentVariants.li}>Aenean nec tortor orci.</Content> + <Content component={ContentVariants.li}>Quisque aliquam cursus urna, non bibendum massa viverra eget.</Content> + <Content component={ContentVariants.li}>Vivamus maximus ultricies pulvinar.</Content> + </Content> +); diff --git a/packages/react-core/src/components/Content/examples/ContentPlainList.tsx b/packages/react-core/src/components/Content/examples/ContentPlainList.tsx new file mode 100644 index 00000000000..13433226326 --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentPlainList.tsx @@ -0,0 +1,27 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentPlainList: React.FunctionComponent = () => ( + <> + <Content component={ContentVariants.h3}>Plain unordered list</Content> + <Content component={ContentVariants.ul} isPlainList> + <Content component={ContentVariants.li}>In fermentum leo eu lectus mollis, quis dictum mi aliquet.</Content> + <Content component={ContentVariants.li}>Morbi eu nulla lobortis, lobortis est in, fringilla felis.</Content> + <Content component={ContentVariants.li}> + Aliquam nec felis in sapien venenatis viverra fermentum nec lectus. + </Content> + <Content component={ContentVariants.li}>Ut non enim metus.</Content> + </Content> + <Content component={ContentVariants.h3}>Plain ordered list</Content> + <Content component={ContentVariants.ol} isPlainList> + <Content component={ContentVariants.li}>Donec blandit a lorem id convallis.</Content> + <Content component={ContentVariants.li}> + {' '} + component={ContentVariants.li}Cras gravida arcu at diam gravida gravida. + </Content> + <Content component={ContentVariants.li}>Integer in volutpat libero.</Content> + <Content component={ContentVariants.li}>Aenean nec tortor orci.</Content> + <Content component={ContentVariants.li}>Quisque aliquam cursus urna, non bibendum massa viverra eget.</Content> + <Content component={ContentVariants.li}>Vivamus maximus ultricies pulvinar.</Content> + </Content> + </> +); diff --git a/packages/react-core/src/components/Content/examples/ContentUnorderedList.tsx b/packages/react-core/src/components/Content/examples/ContentUnorderedList.tsx new file mode 100644 index 00000000000..d3eade8d88e --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentUnorderedList.tsx @@ -0,0 +1,16 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentUnorderedList: React.FunctionComponent = () => ( + <Content component={ContentVariants.ul}> + <Content component={ContentVariants.li}>In fermentum leo eu lectus mollis, quis dictum mi aliquet.</Content> + <Content component={ContentVariants.li}>Morbi eu nulla lobortis, lobortis est in, fringilla felis.</Content> + <Content component={ContentVariants.li}> + Aliquam nec felis in sapien venenatis viverra fermentum nec lectus. + <Content component={ContentVariants.ul}> + <Content component={ContentVariants.li}>In fermentum leo eu lectus mollis, quis dictum mi aliquet.</Content> + <Content component={ContentVariants.li}>Morbi eu nulla lobortis, lobortis est in, fringilla felis.</Content> + </Content> + </Content> + <Content component={ContentVariants.li}>Ut non enim metus.</Content> + </Content> +); diff --git a/packages/react-core/src/components/Content/examples/ContentVisited.tsx b/packages/react-core/src/components/Content/examples/ContentVisited.tsx new file mode 100644 index 00000000000..82ac85ee812 --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentVisited.tsx @@ -0,0 +1,33 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentVisited: React.FunctionComponent = () => ( + <> + <Content> + <Content component={ContentVariants.h3}>Link example</Content> + <Content component={ContentVariants.p}> + <Content component={ContentVariants.a} isVisitedLink href="#"> + Click to visit link + </Content> + </Content> + </Content> + <br /> + <Content isVisitedLink> + <Content component={ContentVariants.h3}>Link content example</Content> + <Content component={ContentVariants.p}> + <Content component={ContentVariants.a} href="#"> + content link 1 + </Content> + </Content> + <Content component={ContentVariants.p}> + <Content component={ContentVariants.a} href="#"> + content link 2 + </Content> + </Content> + <Content component={ContentVariants.p}> + <Content component={ContentVariants.a} href="#"> + content link 3 + </Content> + </Content> + </Content> + </> +); diff --git a/packages/react-core/src/components/Content/examples/ContentWrapper.tsx b/packages/react-core/src/components/Content/examples/ContentWrapper.tsx new file mode 100644 index 00000000000..8e4be41b78a --- /dev/null +++ b/packages/react-core/src/components/Content/examples/ContentWrapper.tsx @@ -0,0 +1,10 @@ +import { Content, ContentVariants } from '@patternfly/react-core'; + +export const ContentWrapper: React.FunctionComponent = () => ( + <Content> + <Content component={ContentVariants.p}> + Content with a component of type "p" still renders the same when wrapped with a Content. + </Content> + <p>If located within a wrapping Content, html elements are styled as well!</p> + </Content> +); diff --git a/packages/react-core/src/components/Content/index.ts b/packages/react-core/src/components/Content/index.ts new file mode 100644 index 00000000000..b39182a1a2f --- /dev/null +++ b/packages/react-core/src/components/Content/index.ts @@ -0,0 +1 @@ +export * from './Content'; diff --git a/packages/react-core/src/components/ContextSelector/ContextSelector.tsx b/packages/react-core/src/components/ContextSelector/ContextSelector.tsx deleted file mode 100644 index 1a7c356dc7e..00000000000 --- a/packages/react-core/src/components/ContextSelector/ContextSelector.tsx +++ /dev/null @@ -1,210 +0,0 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/ContextSelector/context-selector'; -import { css } from '@patternfly/react-styles'; -import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; -import { ContextSelectorToggle } from './ContextSelectorToggle'; -import { ContextSelectorMenuList } from './ContextSelectorMenuList'; -import { ContextSelectorContext } from './contextSelectorConstants'; -import { Button, ButtonVariant } from '../Button'; -import { TextInput } from '../TextInput'; -import { InputGroup } from '../InputGroup'; -import { KEY_CODES } from '../../helpers/constants'; -import { FocusTrap } from '../../helpers'; -import { ToggleMenuBaseProps } from '../../helpers/Popper/Popper'; -import { Popper } from '../../helpers/Popper/Popper'; -import { getOUIAProps, OUIAProps, getDefaultOUIAId } from '../../helpers'; - -// seed for the aria-labelledby ID -let currentId = 0; -const newId = currentId++; - -export interface ContextSelectorProps extends ToggleMenuBaseProps, OUIAProps { - /** content rendered inside the Context Selector */ - children?: React.ReactNode; - /** Classes applied to root element of Context Selector */ - className?: string; - /** Flag to indicate if Context Selector is opened */ - isOpen?: boolean; - /** Function callback called when user clicks toggle button */ - onToggle?: (event: any, value: boolean) => void; - /** Function callback called when user selects item */ - onSelect?: (event: any, value: React.ReactNode) => void; - /** Flag indicating that the context selector should expand to full height */ - isFullHeight?: boolean; - /** Labels the Context Selector for Screen Readers */ - screenReaderLabel?: string; - /** Text that appears in the Context Selector Toggle */ - toggleText?: string; - /** Aria-label for the Context Selector Search Button */ - searchButtonAriaLabel?: string; - /** Value in the Search field */ - searchInputValue?: string; - /** Function callback called when user changes the Search Input */ - onSearchInputChange?: (value: string) => void; - /** Search Input placeholder */ - searchInputPlaceholder?: string; - /** Function callback for when Search Button is clicked */ - onSearchButtonClick?: (event?: React.SyntheticEvent<HTMLButtonElement>) => void; - /** Footer of the context selector */ - footer?: React.ReactNode; - /** Flag to indicate the toggle has no border or background */ - isPlain?: boolean; - /** Flag to indicate if toggle is textual toggle */ - isText?: boolean; - /** Flag to disable focus trap */ - disableFocusTrap?: boolean; -} - -export class ContextSelector extends React.Component<ContextSelectorProps, { ouiaStateId: string }> { - static displayName = 'ContextSelector'; - static defaultProps: ContextSelectorProps = { - children: null as React.ReactNode, - className: '', - isOpen: false, - onToggle: () => undefined as any, - onSelect: () => undefined as any, - screenReaderLabel: '', - toggleText: '', - searchButtonAriaLabel: 'Search menu items', - searchInputValue: '', - onSearchInputChange: () => undefined as any, - searchInputPlaceholder: 'Search', - onSearchButtonClick: () => undefined as any, - menuAppendTo: 'inline', - ouiaSafe: true, - disableFocusTrap: false, - footer: null as React.ReactNode, - isPlain: false, - isText: false - }; - constructor(props: ContextSelectorProps) { - super(props); - this.state = { - ouiaStateId: getDefaultOUIAId(ContextSelector.displayName) - }; - } - - parentRef: React.RefObject<HTMLDivElement> = React.createRef(); - - onEnterPressed = (event: any) => { - if (event.charCode === KEY_CODES.ENTER) { - this.props.onSearchButtonClick(); - } - }; - - render() { - const toggleId = `pf-context-selector-toggle-id-${newId}`; - const screenReaderLabelId = `pf-context-selector-label-id-${newId}`; - const searchButtonId = `pf-context-selector-search-button-id-${newId}`; - const { - children, - className, - isOpen, - isFullHeight, - onToggle, - onSelect, - screenReaderLabel, - toggleText, - searchButtonAriaLabel, - searchInputValue, - onSearchInputChange, - searchInputPlaceholder, - onSearchButtonClick, - menuAppendTo, - ouiaId, - ouiaSafe, - isPlain, - isText, - footer, - disableFocusTrap, - ...props - } = this.props; - const menuContainer = ( - <div className={css(styles.contextSelectorMenu)}> - {isOpen && ( - <FocusTrap active={!disableFocusTrap} focusTrapOptions={{ clickOutsideDeactivates: true }}> - <div className={css(styles.contextSelectorMenuSearch)}> - <InputGroup> - <TextInput - value={searchInputValue} - type="search" - placeholder={searchInputPlaceholder} - onChange={onSearchInputChange} - onKeyPress={this.onEnterPressed} - aria-labelledby={searchButtonId} - /> - <Button - variant={ButtonVariant.control} - aria-label={searchButtonAriaLabel} - id={searchButtonId} - onClick={onSearchButtonClick} - > - <SearchIcon aria-hidden="true" /> - </Button> - </InputGroup> - </div> - <ContextSelectorContext.Provider value={{ onSelect }}> - <ContextSelectorMenuList isOpen={isOpen}>{children}</ContextSelectorMenuList> - </ContextSelectorContext.Provider> - {footer} - </FocusTrap> - )} - </div> - ); - const popperContainer = ( - <div - className={css(styles.contextSelector, isOpen && styles.modifiers.expanded, className)} - ref={this.parentRef} - {...props} - > - {isOpen && menuContainer} - </div> - ); - const mainContainer = ( - <div - className={css( - styles.contextSelector, - isOpen && styles.modifiers.expanded, - isFullHeight && styles.modifiers.fullHeight, - className - )} - ref={this.parentRef} - {...getOUIAProps(ContextSelector.displayName, ouiaId !== undefined ? ouiaId : this.state.ouiaStateId, ouiaSafe)} - {...props} - > - {screenReaderLabel && ( - <span id={screenReaderLabelId} hidden> - {screenReaderLabel} - </span> - )} - <ContextSelectorToggle - onToggle={onToggle} - isOpen={isOpen} - toggleText={toggleText} - id={toggleId} - parentRef={this.parentRef.current} - aria-labelledby={`${screenReaderLabelId} ${toggleId}`} - isPlain={isPlain} - isText={isText} - /> - {isOpen && menuAppendTo === 'inline' && menuContainer} - </div> - ); - const getParentElement = () => { - if (this.parentRef && this.parentRef.current) { - return this.parentRef.current.parentElement; - } - return null; - }; - return menuAppendTo === 'inline' ? ( - mainContainer - ) : ( - <Popper - trigger={mainContainer} - popper={popperContainer} - appendTo={menuAppendTo === 'parent' ? getParentElement() : menuAppendTo} - isVisible={isOpen} - /> - ); - } -} diff --git a/packages/react-core/src/components/ContextSelector/ContextSelectorFooter.tsx b/packages/react-core/src/components/ContextSelector/ContextSelectorFooter.tsx deleted file mode 100644 index d4cfc0dbe6c..00000000000 --- a/packages/react-core/src/components/ContextSelector/ContextSelectorFooter.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/ContextSelector/context-selector'; - -export interface ContextSelectorFooterProps extends React.HTMLProps<HTMLDivElement> { - /** Content rendered inside the ContextSelectorFooter */ - children?: React.ReactNode; - /** Additional classes added to the ContextSelectorFooter */ - className?: string; -} - -export const ContextSelectorFooter: React.FunctionComponent<ContextSelectorFooterProps> = ({ - children = null, - className = '', - ...props -}: ContextSelectorFooterProps) => ( - <div {...props} className={css(styles.contextSelectorMenuFooter, className)}> - {children} - </div> -); -ContextSelectorFooter.displayName = 'ContextSelectorFooter'; diff --git a/packages/react-core/src/components/ContextSelector/ContextSelectorItem.tsx b/packages/react-core/src/components/ContextSelector/ContextSelectorItem.tsx deleted file mode 100644 index 282a2760c47..00000000000 --- a/packages/react-core/src/components/ContextSelector/ContextSelectorItem.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/ContextSelector/context-selector'; -import { css } from '@patternfly/react-styles'; -import { ContextSelectorContext } from './contextSelectorConstants'; - -export interface ContextSelectorItemProps { - /** Anything which can be rendered as Context Selector item */ - children?: React.ReactNode; - /** Classes applied to root element of the Context Selector item */ - className?: string; - /** Render Context Selector item as disabled */ - isDisabled?: boolean; - /** Callback for click event */ - onClick: (event: React.MouseEvent) => void; - /** @hide internal index of the item */ - index: number; - /** Internal callback for ref tracking */ - sendRef: (index: number, current: any) => void; - /** Link href, indicates item should render as anchor tag */ - href?: string; -} - -export class ContextSelectorItem extends React.Component<ContextSelectorItemProps> { - static displayName = 'ContextSelectorItem'; - static defaultProps: ContextSelectorItemProps = { - children: null as React.ReactNode, - className: '', - isDisabled: false, - onClick: (): any => undefined, - index: undefined as number, - sendRef: () => {}, - href: null as string - }; - - ref: React.RefObject<HTMLButtonElement & HTMLAnchorElement> = React.createRef(); - - componentDidMount() { - /* eslint-disable-next-line */ - this.props.sendRef(this.props.index, this.ref.current); - } - - render() { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { className, children, onClick, isDisabled, index, sendRef, href, ...props } = this.props; - const Component = href ? 'a' : 'button'; - const isDisabledLink = href && isDisabled; - return ( - <ContextSelectorContext.Consumer> - {({ onSelect }) => ( - <li role="none"> - <Component - className={css( - styles.contextSelectorMenuListItem, - isDisabledLink && styles.modifiers.disabled, - className - )} - ref={this.ref} - onClick={event => { - if (!isDisabled) { - onClick(event); - onSelect(event, children); - } - }} - disabled={isDisabled && !href} - href={href} - {...(isDisabledLink && { 'aria-disabled': true, tabIndex: -1 })} - {...props} - > - {children} - </Component> - </li> - )} - </ContextSelectorContext.Consumer> - ); - } -} diff --git a/packages/react-core/src/components/ContextSelector/ContextSelectorMenuList.tsx b/packages/react-core/src/components/ContextSelector/ContextSelectorMenuList.tsx deleted file mode 100644 index 1725a501a26..00000000000 --- a/packages/react-core/src/components/ContextSelector/ContextSelectorMenuList.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/ContextSelector/context-selector'; -import { css } from '@patternfly/react-styles'; - -export interface ContextSelectorMenuListProps { - /** Content rendered inside the Context Selector Menu */ - children?: React.ReactNode; - /** Classess applied to root element of Context Selector menu */ - className?: string; - /** Flag to indicate if Context Selector menu is opened */ - isOpen?: boolean; -} - -export class ContextSelectorMenuList extends React.Component<ContextSelectorMenuListProps> { - static displayName = 'ContextSelectorMenuList'; - static defaultProps: ContextSelectorMenuListProps = { - children: null as React.ReactNode, - className: '', - isOpen: true - }; - - refsCollection = [] as any; - - sendRef = (index: number, ref: any) => { - this.refsCollection[index] = ref; - }; - - extendChildren() { - return React.Children.map(this.props.children, (child, index) => - React.cloneElement(child as React.ReactElement<any>, { - sendRef: this.sendRef, - index - }) - ); - } - - render = () => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { className, isOpen, children, ...props } = this.props; - return ( - <ul className={css(styles.contextSelectorMenuList, className)} hidden={!isOpen} role="menu" {...props}> - {this.extendChildren()} - </ul> - ); - }; -} diff --git a/packages/react-core/src/components/ContextSelector/ContextSelectorToggle.tsx b/packages/react-core/src/components/ContextSelector/ContextSelectorToggle.tsx deleted file mode 100644 index f0055948e94..00000000000 --- a/packages/react-core/src/components/ContextSelector/ContextSelectorToggle.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import * as React from 'react'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; -import styles from '@patternfly/react-styles/css/components/ContextSelector/context-selector'; -import { css } from '@patternfly/react-styles'; -import { KEY_CODES } from '../../helpers/constants'; -import { PickOptional } from '../../helpers/typeUtils'; - -export interface ContextSelectorToggleProps { - /** HTML ID of toggle */ - id: string; - /** Classes applied to root element of toggle */ - className?: string; - /** Text that appears in the Context Selector Toggle */ - toggleText?: string; - /** Flag to indicate if menu is opened */ - isOpen?: boolean; - /** Callback called when toggle is clicked */ - onToggle?: (event: any, value: boolean) => void; - /** Callback for toggle open on keyboard entry */ - onEnter?: () => void; - /** Element which wraps toggle */ - parentRef?: any; - /** Forces active state */ - isActive?: boolean; - /** Flag to indicate the toggle has no border or background */ - isPlain?: boolean; - /** Flag to indicate if toggle is textual toggle */ - isText?: boolean; -} - -export class ContextSelectorToggle extends React.Component<ContextSelectorToggleProps> { - static displayName = 'ContextSelectorToggle'; - static defaultProps: PickOptional<ContextSelectorToggleProps> = { - className: '', - toggleText: '', - isOpen: false, - onEnter: () => undefined as any, - parentRef: null as any, - isActive: false, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onToggle: (event: any, value: boolean) => undefined as any - }; - - toggle: React.RefObject<HTMLButtonElement> = React.createRef(); - - componentDidMount = () => { - document.addEventListener('mousedown', this.onDocClick); - document.addEventListener('touchstart', this.onDocClick); - document.addEventListener('keydown', this.onEscPress); - }; - - componentWillUnmount = () => { - document.removeEventListener('mousedown', this.onDocClick); - document.removeEventListener('touchstart', this.onDocClick); - document.removeEventListener('keydown', this.onEscPress); - }; - - onDocClick = (event: any) => { - const { isOpen, parentRef, onToggle } = this.props; - if (isOpen && parentRef && !parentRef.contains(event.target)) { - onToggle(null, false); - this.toggle.current.focus(); - } - }; - - onEscPress = (event: any) => { - const { isOpen, parentRef, onToggle } = this.props; - const keyCode = event.keyCode || event.which; - if (isOpen && keyCode === KEY_CODES.ESCAPE_KEY && parentRef && parentRef.contains(event.target)) { - onToggle(null, false); - this.toggle.current.focus(); - } - }; - - onKeyDown = (event: any) => { - const { isOpen, onToggle, onEnter } = this.props; - if ((event.keyCode === KEY_CODES.TAB && !isOpen) || event.key !== KEY_CODES.ENTER) { - return; - } - event.preventDefault(); - if ( - (event.keyCode === KEY_CODES.TAB || event.keyCode === KEY_CODES.ENTER || event.key !== KEY_CODES.SPACE) && - isOpen - ) { - onToggle(null, !isOpen); - } else if ((event.keyCode === KEY_CODES.ENTER || event.key === ' ') && !isOpen) { - onToggle(null, !isOpen); - onEnter(); - } - }; - - render() { - const { - className, - toggleText, - isOpen, - onToggle, - id, - isPlain, - isText, - /* eslint-disable @typescript-eslint/no-unused-vars */ - isActive, - onEnter, - parentRef, - /* eslint-enable @typescript-eslint/no-unused-vars */ - ...props - } = this.props; - return ( - <button - {...props} - id={id} - ref={this.toggle} - className={css( - styles.contextSelectorToggle, - isActive && styles.modifiers.active, - isPlain && styles.modifiers.plain, - isText && styles.modifiers.text, - className - )} - type="button" - onClick={event => onToggle(event, !isOpen)} - aria-expanded={isOpen} - onKeyDown={this.onKeyDown} - > - <span className={css(styles.contextSelectorToggleText)}>{toggleText}</span> - <span className={css(styles.contextSelectorToggleIcon)}> - <CaretDownIcon aria-hidden /> - </span> - </button> - ); - } -} diff --git a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelector.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/ContextSelector.test.tsx deleted file mode 100644 index 62afc86d3ff..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; -import { ContextSelector } from '../ContextSelector'; -import { ContextSelectorItem } from '../ContextSelectorItem'; - -const items = [ - <ContextSelectorItem key="0">My Project</ContextSelectorItem>, - <ContextSelectorItem key="1">OpenShift Cluster</ContextSelectorItem>, - <ContextSelectorItem key="2">Production Ansible</ContextSelectorItem>, - <ContextSelectorItem key="3">AWS</ContextSelectorItem>, - <ContextSelectorItem key="4">Azure</ContextSelectorItem> -]; - -test('Renders ContextSelector', () => { - const view = shallow(<ContextSelector> {items} </ContextSelector>); - expect(view).toMatchSnapshot(); -}); - -test('Renders ContextSelector open', () => { - const view = shallow(<ContextSelector isOpen> {items} </ContextSelector>); - expect(view).toMatchSnapshot(); -}); - -test('Verify onToggle is called ', () => { - const mockfn = jest.fn(); - const view = mount(<ContextSelector onToggle={mockfn}> {items} </ContextSelector>); - view - .find('button') - .at(0) - .simulate('click'); - expect(mockfn.mock.calls).toHaveLength(1); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorFooter.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorFooter.test.tsx deleted file mode 100644 index de328de7a26..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorFooter.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; -import { ContextSelectorFooter } from '../ContextSelectorFooter'; - -test('Renders ContextSelectorFooter', () => { - const view = shallow(<ContextSelectorFooter>testing text</ContextSelectorFooter>); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorItem.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorItem.test.tsx deleted file mode 100644 index 461334721c7..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorItem.test.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; -import { ContextSelectorItem } from '../ContextSelectorItem'; - -test('Renders ContextSelectorItem', () => { - const view = shallow( - <ContextSelectorItem sendRef={jest.fn()} index={0}> - My Project - </ContextSelectorItem> - ); - expect(view).toMatchSnapshot(); -}); - -test('Renders ContextSelectorItem disabled and hovered', () => { - const view = shallow( - <ContextSelectorItem isDisabled sendRef={jest.fn()} index={0}> - My Project - </ContextSelectorItem> - ); - expect(view).toMatchSnapshot(); -}); - -test('Verify onClick is called ', () => { - const mockfn = jest.fn(); - const view = mount( - <ContextSelectorItem onClick={mockfn} sendRef={jest.fn()} index={0}> - My Project - </ContextSelectorItem> - ); - view - .find('button') - .at(0) - .simulate('click'); - expect(mockfn.mock.calls).toHaveLength(1); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorMenuList.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorMenuList.test.tsx deleted file mode 100644 index 537764daed8..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorMenuList.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import { ContextSelectorItem } from '../ContextSelectorItem'; -import { ContextSelectorMenuList } from '../ContextSelectorMenuList'; - -const items = [ - <ContextSelectorItem key="0">My Project</ContextSelectorItem>, - <ContextSelectorItem key="1">OpenShift Cluster</ContextSelectorItem>, - <ContextSelectorItem key="2">Production Ansible</ContextSelectorItem>, - <ContextSelectorItem key="3">AWS</ContextSelectorItem>, - <ContextSelectorItem key="4">Azure</ContextSelectorItem> -]; - -test('Renders ContextSelectorMenuList open', () => { - const view = shallow(<ContextSelectorMenuList isOpen={false}>{items}</ContextSelectorMenuList>); - expect(view).toMatchSnapshot(); -}); - -test('Renders ContextSelectorMenuList closed', () => { - const view = shallow(<ContextSelectorMenuList isOpen={false}>{items}</ContextSelectorMenuList>); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorToggle.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorToggle.test.tsx deleted file mode 100644 index bfca14b418d..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/ContextSelectorToggle.test.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; -import { ContextSelectorToggle } from '../ContextSelectorToggle'; - -test('Renders ContextSelectorToggle', () => { - const view = shallow(<ContextSelectorToggle id="toggle-id" />); - expect(view).toMatchSnapshot(); -}); - -test('Verify onToggle is called ', () => { - const mockfnOnToggle = jest.fn(); - const view = mount(<ContextSelectorToggle onToggle={mockfnOnToggle} id="toggle-id" />); - view - .find('button') - .at(0) - .simulate('click'); - expect(mockfnOnToggle.mock.calls).toHaveLength(1); -}); - -test('Verify ESC press ', () => { - const view = mount(<ContextSelectorToggle isOpen id="toggle-id" />); - view.simulate('keyDown', { key: 'Escape' }); - expect(view).toMatchSnapshot(); -}); - -test('Verify ESC press with not isOpen', () => { - const view = mount(<ContextSelectorToggle onToggle={jest.fn()} id="toggle-id" />); - view.simulate('keyDown', { key: 'Escape' }); - expect(view).toMatchSnapshot(); -}); - -test('Verify keydown tab ', () => { - const view = mount(<ContextSelectorToggle isOpen id="toggle-id" />); - view.simulate('keyDown', { key: 'Tab' }); - expect(view).toMatchSnapshot(); -}); - -test('Verify keydown enter ', () => { - const view = mount(<ContextSelectorToggle onToggle={jest.fn()} onEnter={jest.fn()} id="toggle-id" />); - view.simulate('keyDown', { key: 'Enter' }); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelector.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelector.test.tsx deleted file mode 100644 index c0888b37880..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelector.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ContextSelector } from '../../ContextSelector'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ContextSelector should match snapshot (auto-generated)', () => { - const view = shallow( - <ContextSelector - children={<>ReactNode</>} - className={"''"} - isOpen={false} - onToggle={() => undefined as any} - onSelect={() => undefined as any} - screenReaderLabel={"''"} - toggleText={"''"} - searchButtonAriaLabel={"'Search menu items'"} - searchInputValue={"''"} - onSearchInputChange={() => undefined as any} - searchInputPlaceholder={"'Search'"} - onSearchButtonClick={() => undefined as any} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorItem.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorItem.test.tsx deleted file mode 100644 index c09585a0144..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorItem.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ContextSelectorItem } from '../../ContextSelectorItem'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ContextSelectorItem should match snapshot (auto-generated)', () => { - const view = shallow( - <ContextSelectorItem - children={<>ReactNode</>} - className={"''"} - isDisabled={false} - isHovered={false} - onClick={(): any => undefined} - index={42} - sendRef={() => {}} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorMenuList.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorMenuList.test.tsx deleted file mode 100644 index 94055748dab..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorMenuList.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ContextSelectorMenuList } from '../../ContextSelectorMenuList'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ContextSelectorMenuList should match snapshot (auto-generated)', () => { - const view = shallow(<ContextSelectorMenuList children={<>ReactNode</>} className={"''"} isOpen={true} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorToggle.test.tsx b/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorToggle.test.tsx deleted file mode 100644 index 003086cffda..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/ContextSelectorToggle.test.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ContextSelectorToggle } from '../../ContextSelectorToggle'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ContextSelectorToggle should match snapshot (auto-generated)', () => { - const view = shallow( - <ContextSelectorToggle - id={'string'} - className={"''"} - toggleText={"''"} - isOpen={false} - onToggle={(event: any, value: boolean) => undefined as any} - onEnter={() => undefined as any} - parentRef={null} - isFocused={false} - isHovered={false} - isActive={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelector.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelector.test.tsx.snap deleted file mode 100644 index f7e5cc7177f..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelector.test.tsx.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ContextSelector should match snapshot (auto-generated) 1`] = ` -<div - className="pf-c-context-selector ''" - data-ouia-component-id="OUIA-Generated-ContextSelector-1" - data-ouia-component-type="PF4/ContextSelector" - data-ouia-safe={true} -> - <span - hidden={true} - id="pf-context-selector-label-id-0" - > - '' - </span> - <ContextSelectorToggle - aria-labelledby="pf-context-selector-label-id-0 pf-context-selector-toggle-id-0" - className="" - id="pf-context-selector-toggle-id-0" - isActive={false} - isOpen={false} - isPlain={false} - isText={false} - onEnter={[Function]} - onToggle={[Function]} - parentRef={null} - toggleText="''" - /> -</div> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorItem.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorItem.test.tsx.snap deleted file mode 100644 index c9efa360908..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorItem.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ContextSelectorItem should match snapshot (auto-generated) 1`] = ` -<ContextConsumer> - <Component /> -</ContextConsumer> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorMenuList.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorMenuList.test.tsx.snap deleted file mode 100644 index 955eb12c5ca..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorMenuList.test.tsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ContextSelectorMenuList should match snapshot (auto-generated) 1`] = ` -<ul - className="pf-c-context-selector__menu-list ''" - hidden={false} - role="menu" -> - ReactNode -</ul> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorToggle.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorToggle.test.tsx.snap deleted file mode 100644 index 3fa8fb0bc23..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/Generated/__snapshots__/ContextSelectorToggle.test.tsx.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ContextSelectorToggle should match snapshot (auto-generated) 1`] = ` -<button - aria-expanded={false} - className="pf-c-context-selector__toggle ''" - id="string" - isFocused={false} - isHovered={false} - onClick={[Function]} - onKeyDown={[Function]} - type="button" -> - <span - className="pf-c-context-selector__toggle-text" - > - '' - </span> - <span - className="pf-c-context-selector__toggle-icon" - > - <CaretDownIcon - aria-hidden={true} - color="currentColor" - noVerticalAlign={false} - size="sm" - /> - </span> -</button> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap deleted file mode 100644 index a552c5f524a..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap +++ /dev/null @@ -1,154 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Renders ContextSelector 1`] = ` -<div - className="pf-c-context-selector" - data-ouia-component-id="OUIA-Generated-ContextSelector-1" - data-ouia-component-type="PF4/ContextSelector" - data-ouia-safe={true} -> - <ContextSelectorToggle - aria-labelledby="pf-context-selector-label-id-0 pf-context-selector-toggle-id-0" - className="" - id="pf-context-selector-toggle-id-0" - isActive={false} - isOpen={false} - isPlain={false} - isText={false} - onEnter={[Function]} - onToggle={[Function]} - parentRef={null} - toggleText="" - /> -</div> -`; - -exports[`Renders ContextSelector open 1`] = ` -<div - className="pf-c-context-selector pf-m-expanded" - data-ouia-component-id="OUIA-Generated-ContextSelector-2" - data-ouia-component-type="PF4/ContextSelector" - data-ouia-safe={true} -> - <ContextSelectorToggle - aria-labelledby="pf-context-selector-label-id-0 pf-context-selector-toggle-id-0" - className="" - id="pf-context-selector-toggle-id-0" - isActive={false} - isOpen={true} - isPlain={false} - isText={false} - onEnter={[Function]} - onToggle={[Function]} - parentRef={null} - toggleText="" - /> - <div - className="pf-c-context-selector__menu" - > - <FocusTrap - active={true} - focusTrapOptions={ - Object { - "clickOutsideDeactivates": true, - } - } - paused={false} - preventScrollOnDeactivate={false} - > - <div - className="pf-c-context-selector__menu-search" - > - <InputGroup> - <TextInput - aria-labelledby="pf-context-selector-search-button-id-0" - onChange={[Function]} - onKeyPress={[Function]} - placeholder="Search" - type="search" - value="" - /> - <Button - aria-label="Search menu items" - id="pf-context-selector-search-button-id-0" - onClick={[Function]} - variant="control" - > - <SearchIcon - aria-hidden="true" - color="currentColor" - noVerticalAlign={false} - size="sm" - /> - </Button> - </InputGroup> - </div> - <ContextProvider - value={ - Object { - "onSelect": [Function], - } - } - > - <ContextSelectorMenuList - className="" - isOpen={true} - > - - <ContextSelectorItem - className="" - href={null} - isDisabled={false} - key="0" - onClick={[Function]} - sendRef={[Function]} - > - My Project - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - isDisabled={false} - key="1" - onClick={[Function]} - sendRef={[Function]} - > - OpenShift Cluster - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - isDisabled={false} - key="2" - onClick={[Function]} - sendRef={[Function]} - > - Production Ansible - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - isDisabled={false} - key="3" - onClick={[Function]} - sendRef={[Function]} - > - AWS - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - isDisabled={false} - key="4" - onClick={[Function]} - sendRef={[Function]} - > - Azure - </ContextSelectorItem> - - </ContextSelectorMenuList> - </ContextProvider> - </FocusTrap> - </div> -</div> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorFooter.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorFooter.test.tsx.snap deleted file mode 100644 index f21532d15db..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorFooter.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Renders ContextSelectorFooter 1`] = ` -<div - className="pf-c-context-selector__menu-footer" -> - testing text -</div> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorItem.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorItem.test.tsx.snap deleted file mode 100644 index d491ae77586..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorItem.test.tsx.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Renders ContextSelectorItem 1`] = ` -<ContextConsumer> - <Component /> -</ContextConsumer> -`; - -exports[`Renders ContextSelectorItem disabled and hovered 1`] = ` -<ContextConsumer> - <Component /> -</ContextConsumer> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorMenuList.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorMenuList.test.tsx.snap deleted file mode 100644 index 40dcd09f70a..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorMenuList.test.tsx.snap +++ /dev/null @@ -1,129 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Renders ContextSelectorMenuList closed 1`] = ` -<ul - className="pf-c-context-selector__menu-list" - hidden={true} - role="menu" -> - <ContextSelectorItem - className="" - href={null} - index={0} - isDisabled={false} - key=".$0" - onClick={[Function]} - sendRef={[Function]} - > - My Project - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={1} - isDisabled={false} - key=".$1" - onClick={[Function]} - sendRef={[Function]} - > - OpenShift Cluster - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={2} - isDisabled={false} - key=".$2" - onClick={[Function]} - sendRef={[Function]} - > - Production Ansible - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={3} - isDisabled={false} - key=".$3" - onClick={[Function]} - sendRef={[Function]} - > - AWS - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={4} - isDisabled={false} - key=".$4" - onClick={[Function]} - sendRef={[Function]} - > - Azure - </ContextSelectorItem> -</ul> -`; - -exports[`Renders ContextSelectorMenuList open 1`] = ` -<ul - className="pf-c-context-selector__menu-list" - hidden={true} - role="menu" -> - <ContextSelectorItem - className="" - href={null} - index={0} - isDisabled={false} - key=".$0" - onClick={[Function]} - sendRef={[Function]} - > - My Project - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={1} - isDisabled={false} - key=".$1" - onClick={[Function]} - sendRef={[Function]} - > - OpenShift Cluster - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={2} - isDisabled={false} - key=".$2" - onClick={[Function]} - sendRef={[Function]} - > - Production Ansible - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={3} - isDisabled={false} - key=".$3" - onClick={[Function]} - sendRef={[Function]} - > - AWS - </ContextSelectorItem> - <ContextSelectorItem - className="" - href={null} - index={4} - isDisabled={false} - key=".$4" - onClick={[Function]} - sendRef={[Function]} - > - Azure - </ContextSelectorItem> -</ul> -`; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorToggle.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorToggle.test.tsx.snap deleted file mode 100644 index e0a8a7476eb..00000000000 --- a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorToggle.test.tsx.snap +++ /dev/null @@ -1,246 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Renders ContextSelectorToggle 1`] = ` -<button - aria-expanded={false} - className="pf-c-context-selector__toggle" - id="toggle-id" - onClick={[Function]} - onKeyDown={[Function]} - type="button" -> - <span - className="pf-c-context-selector__toggle-text" - /> - <span - className="pf-c-context-selector__toggle-icon" - > - <CaretDownIcon - aria-hidden={true} - color="currentColor" - noVerticalAlign={false} - size="sm" - /> - </span> -</button> -`; - -exports[`Verify ESC press 1`] = ` -<ContextSelectorToggle - className="" - id="toggle-id" - isActive={false} - isOpen={true} - onEnter={[Function]} - onToggle={[Function]} - parentRef={null} - toggleText="" -> - <button - aria-expanded={true} - className="pf-c-context-selector__toggle" - id="toggle-id" - onClick={[Function]} - onKeyDown={[Function]} - type="button" - > - <span - className="pf-c-context-selector__toggle-text" - /> - <span - className="pf-c-context-selector__toggle-icon" - > - <CaretDownIcon - aria-hidden={true} - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 320 512" - width="1em" - > - <path - d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" - /> - </svg> - </CaretDownIcon> - </span> - </button> -</ContextSelectorToggle> -`; - -exports[`Verify ESC press with not isOpen 1`] = ` -<ContextSelectorToggle - className="" - id="toggle-id" - isActive={false} - isOpen={false} - onEnter={[Function]} - onToggle={[MockFunction]} - parentRef={null} - toggleText="" -> - <button - aria-expanded={false} - className="pf-c-context-selector__toggle" - id="toggle-id" - onClick={[Function]} - onKeyDown={[Function]} - type="button" - > - <span - className="pf-c-context-selector__toggle-text" - /> - <span - className="pf-c-context-selector__toggle-icon" - > - <CaretDownIcon - aria-hidden={true} - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 320 512" - width="1em" - > - <path - d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" - /> - </svg> - </CaretDownIcon> - </span> - </button> -</ContextSelectorToggle> -`; - -exports[`Verify keydown enter 1`] = ` -<ContextSelectorToggle - className="" - id="toggle-id" - isActive={false} - isOpen={false} - onEnter={[MockFunction]} - onToggle={[MockFunction]} - parentRef={null} - toggleText="" -> - <button - aria-expanded={false} - className="pf-c-context-selector__toggle" - id="toggle-id" - onClick={[Function]} - onKeyDown={[Function]} - type="button" - > - <span - className="pf-c-context-selector__toggle-text" - /> - <span - className="pf-c-context-selector__toggle-icon" - > - <CaretDownIcon - aria-hidden={true} - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 320 512" - width="1em" - > - <path - d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" - /> - </svg> - </CaretDownIcon> - </span> - </button> -</ContextSelectorToggle> -`; - -exports[`Verify keydown tab 1`] = ` -<ContextSelectorToggle - className="" - id="toggle-id" - isActive={false} - isOpen={true} - onEnter={[Function]} - onToggle={[Function]} - parentRef={null} - toggleText="" -> - <button - aria-expanded={true} - className="pf-c-context-selector__toggle" - id="toggle-id" - onClick={[Function]} - onKeyDown={[Function]} - type="button" - > - <span - className="pf-c-context-selector__toggle-text" - /> - <span - className="pf-c-context-selector__toggle-icon" - > - <CaretDownIcon - aria-hidden={true} - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 320 512" - width="1em" - > - <path - d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" - /> - </svg> - </CaretDownIcon> - </span> - </button> -</ContextSelectorToggle> -`; diff --git a/packages/react-core/src/components/ContextSelector/contextSelectorConstants.tsx b/packages/react-core/src/components/ContextSelector/contextSelectorConstants.tsx deleted file mode 100644 index 05f119ff594..00000000000 --- a/packages/react-core/src/components/ContextSelector/contextSelectorConstants.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from 'react'; - -export const ContextSelectorContext = React.createContext({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onSelect: (event: any, value: React.ReactNode): any => undefined -}); diff --git a/packages/react-core/src/components/ContextSelector/examples/ContextSelector.md b/packages/react-core/src/components/ContextSelector/examples/ContextSelector.md deleted file mode 100644 index 7f29405ca8c..00000000000 --- a/packages/react-core/src/components/ContextSelector/examples/ContextSelector.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -id: Context selector -section: components -propComponents: ['ContextSelector', 'ContextSelectorItem', 'ContextSelectorFooter'] - -ouia: true ---- - -## Examples - -### Basic - -```js -import React from 'react'; -import { Button, ContextSelector, ContextSelectorItem, ContextSelectorFooter } from '@patternfly/react-core'; - -class SimpleContextSelector extends React.Component { - constructor(props) { - super(props); - this.items = [ - { - text: 'Link', - href: '#' - }, - 'Action', - { - text: 'Disabled link', - href: '#', - isDisabled: true - }, - { - text: 'Disabled action', - isDisabled: true - }, - 'My project', - 'OpenShift cluster', - 'Production Ansible', - 'AWS', - 'Azure', - 'My project 2', - 'OpenShift cluster ', - 'Production Ansible 2 ', - 'AWS 2', - 'Azure 2' - ]; - - this.state = { - isOpen: false, - selected: this.items[0].text || this.items[0], - searchValue: '', - filteredItems: this.items - }; - - this.onToggle = (event, isOpen) => { - this.setState({ - isOpen - }); - }; - - this.onSelect = (event, value) => { - this.setState({ - selected: value, - isOpen: !this.state.isOpen - }); - }; - - this.onSearchInputChange = value => { - this.setState({ searchValue: value }); - }; - - this.onSearchButtonClick = event => { - const filtered = - this.state.searchValue === '' - ? this.items - : this.items.filter(item => { - const str = item.text ? item.text : item; - return str.toLowerCase().indexOf(this.state.searchValue.toLowerCase()) !== -1; - }); - - this.setState({ filteredItems: filtered || [] }); - }; - } - - render() { - const { isOpen, selected, searchValue, filteredItems } = this.state; - return ( - <ContextSelector - toggleText={selected} - onSearchInputChange={this.onSearchInputChange} - isOpen={isOpen} - searchInputValue={searchValue} - onToggle={this.onToggle} - onSelect={this.onSelect} - onSearchButtonClick={this.onSearchButtonClick} - screenReaderLabel="Selected Project:" - > - {filteredItems.map((item, index) => { - const { text = null, href = null, isDisabled } = item; - return (<ContextSelectorItem key={index} href={href} isDisabled={isDisabled}>{text || item}</ContextSelectorItem>); - })} - </ContextSelector> - ); - } -} -``` - -### Plain with text - -```ts -import React from 'react'; -import { ContextSelector, ContextSelectorItem } from '@patternfly/react-core'; - -interface Item { - text: string; - href?: string; - isDisabled?: boolean; -} - -const items = [ - { - text: 'Link', - href: '#' - }, - 'Action', - { - text: 'Disabled link', - href: '#', - isDisabled: true - }, - { - text: 'Disabled action', - isDisabled: true - }, - 'My Project', - 'OpenShift Cluster', - 'Production Ansible', - 'AWS', - 'Azure', - 'My Project 2', - 'OpenShift Cluster ', - 'Production Ansible 2 ', - 'AWS 2', - 'Azure 2' -]; - -const PlainTextContextSelector: React.FunctionComponent = () => { - const firstItemText = typeof items[0] === 'string' ? items[0] : items[0].text; - const [isOpen, setOpen] = React.useState(false); - const [selected, setSelected] = React.useState(firstItemText); - const [searchValue, setSearchValue] = React.useState(''); - const [filteredItems, setFilteredItems] = React.useState(items); - - function onToggle(event: any, isOpen: boolean) { - setOpen(isOpen); - }; - - function onSelect(event: any, value: string) { - setSelected(value); - setOpen(!isOpen); - }; - - function onSearchInputChange(value: string) { - setSearchValue(value); - }; - - function onSearchButtonClick(event: React.SyntheticEvent<HTMLButtonElement>) { - const filtered = - searchValue === '' - ? items - : items.filter(item => { - const str = (typeof item === 'string') ? item : item.text; - return str.toLowerCase().indexOf(searchValue.toLowerCase()) !== -1; - }); - - setFilteredItems(filtered || []); - }; - return ( - <ContextSelector - toggleText={selected} - onSearchInputChange={onSearchInputChange} - isOpen={isOpen} - searchInputValue={searchValue} - onToggle={onToggle} - onSelect={onSelect} - onSearchButtonClick={onSearchButtonClick} - screenReaderLabel="Selected Project:" - isPlain - isText - > - {filteredItems.map((item, index) => { - const [text, href = null, isDisabled = false] = (typeof item === 'string') - ? [item, null, false] - : [item.text, item.href, item.isDisabled]; - return <ContextSelectorItem key={index} href={href} isDisabled={isDisabled}>{text}</ContextSelectorItem>; - })} - </ContextSelector> - ); -}; -``` - -### With footer - -```js -import React from 'react'; -import { Button, ContextSelector, ContextSelectorItem, ContextSelectorFooter } from '@patternfly/react-core'; - -class FooterContextSelector extends React.Component { - constructor(props) { - super(props); - this.items = [ - { - text: 'Link', - href: '#' - }, - 'Action', - { - text: 'Disabled link', - href: '#', - isDisabled: true - }, - { - text: 'Disabled action', - isDisabled: true - }, - 'My project', - 'OpenShift cluster', - 'Production Ansible', - 'AWS', - 'Azure', - 'My project 2', - 'OpenShift cluster ', - 'Production Ansible 2 ', - 'AWS 2', - 'Azure 2' - ]; - - this.state = { - isOpen: false, - selected: this.items[0].text || this.items[0], - searchValue: '', - filteredItems: this.items - }; - - this.onToggle = (event, isOpen) => { - this.setState({ - isOpen - }); - }; - - this.onSelect = (event, value) => { - this.setState({ - selected: value, - isOpen: !this.state.isOpen - }); - }; - - this.onSearchInputChange = value => { - this.setState({ searchValue: value }); - }; - - this.onSearchButtonClick = event => { - const filtered = - this.state.searchValue === '' - ? this.items - : this.items.filter(item => { - const str = item.text ? item.text : item; - return str.toLowerCase().indexOf(this.state.searchValue.toLowerCase()) !== -1; - }); - - this.setState({ filteredItems: filtered || [] }); - }; - } - - render() { - const { isOpen, selected, searchValue, filteredItems } = this.state; - return ( - <ContextSelector - toggleText={selected} - onSearchInputChange={this.onSearchInputChange} - isOpen={isOpen} - searchInputValue={searchValue} - onToggle={this.onToggle} - onSelect={this.onSelect} - onSearchButtonClick={this.onSearchButtonClick} - screenReaderLabel="Selected Project:" - footer={ - <ContextSelectorFooter> - <Button variant="link" isInline>Footer action</Button> - </ContextSelectorFooter> - } - > - {filteredItems.map((item, index) => { - const { text = null, href = null, isDisabled } = item; - return (<ContextSelectorItem key={index} href={href} isDisabled={isDisabled}>{text || item}</ContextSelectorItem>); - })} - </ContextSelector> - ); - } -} -``` diff --git a/packages/react-core/src/components/ContextSelector/index.ts b/packages/react-core/src/components/ContextSelector/index.ts deleted file mode 100644 index 587ff1c1eb8..00000000000 --- a/packages/react-core/src/components/ContextSelector/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './ContextSelector'; -export * from './ContextSelectorItem'; -export * from './ContextSelectorFooter'; diff --git a/packages/react-core/src/components/DataList/DataList.tsx b/packages/react-core/src/components/DataList/DataList.tsx index 6c96d4c92dc..d9063b875ba 100644 --- a/packages/react-core/src/components/DataList/DataList.tsx +++ b/packages/react-core/src/components/DataList/DataList.tsx @@ -1,17 +1,15 @@ -import * as React from 'react'; +import { createContext, forwardRef } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; -import stylesGrid from '@patternfly/react-styles/css/components/DataList/data-list-grid'; -import { PickOptional } from '../../helpers/typeUtils'; const gridBreakpointClasses = { - none: stylesGrid.modifiers.gridNone, + none: styles.modifiers.gridNone, always: 'pf-m-grid', // Placeholder per https://github.com/patternfly/patternfly-react/issues/4965#issuecomment-704984236 - sm: stylesGrid.modifiers.gridSm, - md: stylesGrid.modifiers.gridMd, - lg: stylesGrid.modifiers.gridLg, - xl: stylesGrid.modifiers.gridXl, - '2xl': stylesGrid.modifiers.grid_2xl + sm: styles.modifiers.gridSm, + md: styles.modifiers.gridMd, + lg: styles.modifiers.gridLg, + xl: styles.modifiers.gridXl, + '2xl': styles.modifiers.grid_2xl }; export enum DataListWrapModifier { @@ -20,340 +18,100 @@ export enum DataListWrapModifier { breakWord = 'breakWord' } -export interface DataListProps extends Omit<React.HTMLProps<HTMLUListElement>, 'onDragStart' | 'ref'> { - /** Content rendered inside the DataList list */ +export interface DataListProps extends React.HTMLProps<HTMLUListElement> { + /** Content rendered inside the data list list */ children?: React.ReactNode; - /** Additional classes added to the DataList list */ + /** Additional classes added to the data list list */ className?: string; - /** Adds accessible text to the DataList list */ + /** Adds accessible text to the data list list */ 'aria-label': string; - /** Optional callback to make DataList selectable, fired when DataListItem selected */ - onSelectDataListItem?: (id: string) => void; - /** @deprecated Optional callback to make DataList draggable, fired when dragging ends */ - onDragFinish?: (newItemOrder: string[]) => void; - /** @deprecated Optional informational callback for dragging, fired when dragging starts */ - onDragStart?: (id: string) => void; - /** @deprecated Optional informational callback for dragging, fired when an item moves */ - onDragMove?: (oldIndex: number, newIndex: number) => void; - /** @deprecated Optional informational callback for dragging, fired when dragging is cancelled */ - onDragCancel?: () => void; - /** Id of DataList item currently selected */ + /** Optional callback to make data list selectable, fired when data list item selected */ + onSelectDataListItem?: (event: React.MouseEvent | React.KeyboardEvent, id: string) => void; + /** Id of data list item currently selected */ selectedDataListItemId?: string; - /** Flag indicating if DataList should have compact styling */ + /** Flag indicating if data list should have compact styling */ isCompact?: boolean; + /** @beta Flag indicating if data list should have plain styling with a transparent background */ + isPlain?: boolean; + /** @beta Flag to prevent the data list from automatically applying plain styling when glass theme is enabled. */ + isNoPlainOnGlass?: boolean; /** Specifies the grid breakpoints */ gridBreakpoint?: 'none' | 'always' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'; - /** Determines which wrapping modifier to apply to the DataList */ + /** Determines which wrapping modifier to apply to the data list */ wrapModifier?: DataListWrapModifier | 'nowrap' | 'truncate' | 'breakWord'; - /** @deprecated Order of items in a draggable DataList */ - itemOrder?: string[]; -} - -interface DataListState { - draggedItemId: string; - draggingToItemIndex: number; - dragging: boolean; - tempItemOrder: string[]; + /** Object that causes the data list to render hidden inputs which improve selectable item a11y */ + onSelectableRowChange?: (event: React.FormEvent<HTMLInputElement>, id: string) => void; + /** @hide custom ref of the data list */ + innerRef?: React.RefObject<HTMLUListElement | null>; } interface DataListContextProps { isSelectable: boolean; selectedDataListItemId: string; - updateSelectedDataListItem: (id: string) => void; - isDraggable: boolean; - dragStart: (e: React.DragEvent) => void; - dragEnd: (e: React.DragEvent) => void; - drop: (e: React.DragEvent) => void; - dragKeyHandler: (e: React.KeyboardEvent) => void; + updateSelectedDataListItem: (event: React.MouseEvent | React.KeyboardEvent, id: string) => void; + onSelectableRowChange?: (event: React.FormEvent<HTMLInputElement>, id: string) => void; } -export const DataListContext = React.createContext<Partial<DataListContextProps>>({ +export const DataListContext = createContext<Partial<DataListContextProps>>({ isSelectable: false }); -const moveItem = (arr: string[], i1: string, toIndex: number) => { - const fromIndex = arr.indexOf(i1); - if (fromIndex === toIndex) { - return arr; - } - const temp = arr.splice(fromIndex, 1); - arr.splice(toIndex, 0, temp[0]); - - return arr; -}; - -export class DataList extends React.Component<DataListProps, DataListState> { - static displayName = 'DataList'; - static defaultProps: PickOptional<DataListProps> = { - children: null, - className: '', - selectedDataListItemId: '', - isCompact: false, - gridBreakpoint: 'md', - wrapModifier: null - }; - dragFinished: boolean = false; - html5DragDrop: boolean = false; - arrayCopy: React.ReactElement[] = React.Children.toArray(this.props.children) as React.ReactElement[]; - ref = React.createRef<HTMLUListElement>(); - - state: DataListState = { - tempItemOrder: [], - draggedItemId: null, - draggingToItemIndex: null, - dragging: false - }; - - constructor(props: DataListProps) { - super(props); - - this.html5DragDrop = Boolean(props.onDragFinish || props.onDragStart || props.onDragMove || props.onDragCancel); - if (this.html5DragDrop) { - // eslint-disable-next-line no-console - console.warn("DataList's onDrag API is deprecated. Use DragDrop instead."); - } - } - - componentDidUpdate(oldProps: DataListProps) { - if (this.dragFinished) { - this.dragFinished = false; - - this.setState({ - tempItemOrder: [...this.props.itemOrder], - draggedItemId: null, - dragging: false - }); - } - if (oldProps.itemOrder !== this.props.itemOrder) { - this.move(this.props.itemOrder); - } - } - - getIndex = (id: string) => Array.from(this.ref.current.children).findIndex(item => item.id === id); - - move = (itemOrder: string[]) => { - const ulNode = this.ref.current; - const nodes = Array.from(ulNode.children); - if (nodes.map(node => node.id).every((id, i) => id === itemOrder[i])) { - return; - } - while (ulNode.firstChild) { - ulNode.removeChild(ulNode.lastChild); - } - - itemOrder.forEach(id => { - ulNode.appendChild(nodes.find(n => n.id === id)); - }); - }; - - dragStart0 = (el: HTMLElement) => { - const { onDragStart } = this.props; - const draggedItemId = el.id; - - el.classList.add(styles.modifiers.ghostRow); - el.setAttribute('aria-pressed', 'true'); - this.setState({ - draggedItemId, - dragging: true - }); - onDragStart && onDragStart(draggedItemId); +export const DataListBase: React.FunctionComponent<DataListProps> = ({ + children = null, + className = '', + 'aria-label': ariaLabel, + onSelectDataListItem, + selectedDataListItemId = '', + isCompact = false, + isPlain = false, + isNoPlainOnGlass = false, + gridBreakpoint = 'md', + wrapModifier = null, + onSelectableRowChange, + innerRef, + ...props +}: DataListProps) => { + const isSelectable = onSelectDataListItem !== undefined; + + const updateSelectedDataListItem = (event: React.MouseEvent | React.KeyboardEvent, id: string) => { + onSelectDataListItem(event, id); }; - dragStart = (evt: React.DragEvent) => { - evt.dataTransfer.effectAllowed = 'move'; - evt.dataTransfer.setData('text/plain', evt.currentTarget.id); - this.dragStart0(evt.currentTarget as HTMLElement); - }; - - onDragCancel = () => { - this.move(this.props.itemOrder); - Array.from(this.ref.current.children).forEach(el => { - el.classList.remove(styles.modifiers.ghostRow); - el.classList.remove(styles.modifiers.dragOver); - el.setAttribute('aria-pressed', 'false'); - }); - this.setState({ - draggedItemId: null, - draggingToItemIndex: null, - dragging: false - }); - - if (this.props.onDragCancel) { - this.props.onDragCancel(); - } - }; - - dragLeave = (evt: React.DragEvent) => { - // This event false fires when we call `this.move()`, so double check we're out of zone - if (!this.isValidDrop(evt)) { - this.move(this.props.itemOrder); - this.setState({ - draggingToItemIndex: null - }); - } - }; - - dragEnd0 = (el: HTMLElement) => { - el.classList.remove(styles.modifiers.ghostRow); - el.classList.remove(styles.modifiers.dragOver); - el.setAttribute('aria-pressed', 'false'); - this.setState({ - draggedItemId: null, - draggingToItemIndex: null, - dragging: false - }); - }; - - dragEnd = (evt: React.DragEvent) => { - this.dragEnd0(evt.target as HTMLElement); - }; - - isValidDrop = (evt: React.DragEvent) => { - const ulRect = this.ref.current.getBoundingClientRect(); - return ( - evt.clientX > ulRect.x && - evt.clientX < ulRect.x + ulRect.width && - evt.clientY > ulRect.y && - evt.clientY < ulRect.y + ulRect.height - ); - }; - - drop = (evt: React.DragEvent) => { - if (this.isValidDrop(evt)) { - this.props.onDragFinish(this.state.tempItemOrder); - } else { - this.onDragCancel(); - } - }; - - dragOver0 = (id: string) => { - const draggingToItemIndex = Array.from(this.ref.current.children).findIndex(item => item.id === id); - if (draggingToItemIndex !== this.state.draggingToItemIndex) { - const tempItemOrder = moveItem([...this.props.itemOrder], this.state.draggedItemId, draggingToItemIndex); - this.move(tempItemOrder); - - this.setState({ - draggingToItemIndex, - tempItemOrder - }); - } - }; - - dragOver = (evt: React.DragEvent): string | null => { - evt.preventDefault(); - - const curListItem = (evt.target as HTMLElement).closest('li'); - if (!curListItem || !this.ref.current.contains(curListItem) || curListItem.id === this.state.draggedItemId) { - // We're going nowhere, don't bother calling `dragOver0` - return null; - } else { - this.dragOver0(curListItem.id); - } - }; - - handleDragButtonKeys = (evt: React.KeyboardEvent) => { - const { dragging } = this.state; - if (![' ', 'Escape', 'Enter', 'ArrowUp', 'ArrowDown'].includes(evt.key) || !this.html5DragDrop) { - if (dragging) { - evt.preventDefault(); - } - return; - } - evt.preventDefault(); - - const dragItem = (evt.target as Element).closest('li'); - - if (evt.key === ' ' || (evt.key === 'Enter' && !dragging)) { - this.dragStart0(dragItem); - } else if (dragging) { - if (evt.key === 'Escape' || evt.key === 'Enter') { - this.setState({ - dragging: false - }); - this.dragFinished = true; - if (evt.key === 'Enter') { - this.dragEnd0(dragItem); - this.props.onDragFinish(this.state.tempItemOrder); - } else { - this.onDragCancel(); - } - } else if (evt.key === 'ArrowUp') { - const nextSelection = dragItem.previousSibling as HTMLElement; - if (nextSelection) { - this.dragOver0(nextSelection.id); - (dragItem.querySelector(`.${styles.dataListItemDraggableButton}`) as HTMLElement).focus(); - } - } else if (evt.key === 'ArrowDown') { - const nextSelection = dragItem.nextSibling as HTMLElement; - if (nextSelection) { - this.dragOver0(nextSelection.id); - (dragItem.querySelector(`.${styles.dataListItemDraggableButton}`) as HTMLElement).focus(); - } - } - } - }; - - render() { - const { - className, - children, - onSelectDataListItem, - selectedDataListItemId, - isCompact, - wrapModifier, - /* eslint-disable @typescript-eslint/no-unused-vars */ - onDragStart, - onDragMove, - onDragCancel, - onDragFinish, - gridBreakpoint, - itemOrder, - /* eslint-enable @typescript-eslint/no-unused-vars */ - ...props - } = this.props; - const { dragging } = this.state; - const isSelectable = onSelectDataListItem !== undefined; + return ( + <DataListContext.Provider + value={{ + isSelectable, + selectedDataListItemId, + updateSelectedDataListItem, + onSelectableRowChange + }} + > + <ul + className={css( + styles.dataList, + isCompact && styles.modifiers.compact, + isPlain && styles.modifiers.plain, + isNoPlainOnGlass && styles.modifiers.noPlainOnGlass, + gridBreakpointClasses[gridBreakpoint], + wrapModifier && styles.modifiers[wrapModifier], + className + )} + style={props.style} + role="list" + aria-label={ariaLabel} + ref={innerRef} + {...props} + > + {children} + </ul> + </DataListContext.Provider> + ); +}; - const updateSelectedDataListItem = (id: string) => { - onSelectDataListItem(id); - }; +DataListBase.displayName = 'DataListBase'; - const dragProps = this.html5DragDrop && { - onDragOver: this.dragOver, - onDrop: this.dragOver, - onDragLeave: this.dragLeave - }; +export const DataList = forwardRef((props: DataListProps, ref: React.Ref<HTMLUListElement>) => ( + <DataListBase innerRef={ref as React.MutableRefObject<any>} {...props} /> +)); - return ( - <DataListContext.Provider - value={{ - isSelectable, - selectedDataListItemId, - updateSelectedDataListItem, - isDraggable: this.html5DragDrop, - dragStart: this.dragStart, - dragEnd: this.dragEnd, - drop: this.drop, - dragKeyHandler: this.handleDragButtonKeys - }} - > - <ul - className={css( - styles.dataList, - isCompact && styles.modifiers.compact, - gridBreakpointClasses[gridBreakpoint], - wrapModifier && styles.modifiers[wrapModifier], - dragging && styles.modifiers.dragOver, - className - )} - style={props.style} - {...props} - {...dragProps} - ref={this.ref} - > - {children} - </ul> - </DataListContext.Provider> - ); - } -} +DataList.displayName = 'DataList'; diff --git a/packages/react-core/src/components/DataList/DataListAction.tsx b/packages/react-core/src/components/DataList/DataListAction.tsx index 807bf915691..dab1e06dc73 100644 --- a/packages/react-core/src/components/DataList/DataListAction.tsx +++ b/packages/react-core/src/components/DataList/DataListAction.tsx @@ -1,18 +1,17 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; import { formatBreakpointMods } from '../../helpers/util'; export interface DataListActionProps extends Omit<React.HTMLProps<HTMLDivElement>, 'children'> { - /** Content rendered as DataList Action (e.g <Button> or <Dropdown>) */ + /** Content rendered as data list action (e.g <Button> or <Dropdown>) */ children: React.ReactNode; - /** Additional classes added to the DataList Action */ + /** Additional classes added to the data list action */ className?: string; - /** Identify the DataList toggle number */ + /** Identify the data list toggle number */ id: string; - /** Adds accessible text to the DataList Action */ + /** Adds accessible text to the data list action */ 'aria-labelledby': string; - /** Adds accessible text to the DataList Action */ + /** Adds accessible text to the data list action */ 'aria-label': string; /** What breakpoints to hide/show the data list action */ visibility?: { @@ -23,8 +22,6 @@ export interface DataListActionProps extends Omit<React.HTMLProps<HTMLDivElement xl?: 'hidden' | 'visible'; '2xl'?: 'hidden' | 'visible'; }; - /** Flag to indicate that the action is a plain button (e.g. kebab dropdown toggle) so that styling is applied to align the button */ - isPlainButtonAction?: boolean; } export const DataListAction: React.FunctionComponent<DataListActionProps> = ({ @@ -35,12 +32,10 @@ export const DataListAction: React.FunctionComponent<DataListActionProps> = ({ id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, - isPlainButtonAction, - /* eslint-enable @typescript-eslint/no-unused-vars */ ...props }: DataListActionProps) => ( <div className={css(styles.dataListItemAction, formatBreakpointMods(visibility, styles), className)} {...props}> - {isPlainButtonAction ? <div className={css(styles.dataListAction)}>{children}</div> : children} + {children} </div> ); DataListAction.displayName = 'DataListAction'; diff --git a/packages/react-core/src/components/DataList/DataListCell.tsx b/packages/react-core/src/components/DataList/DataListCell.tsx index 287fa91fa5a..4059f794843 100644 --- a/packages/react-core/src/components/DataList/DataListCell.tsx +++ b/packages/react-core/src/components/DataList/DataListCell.tsx @@ -1,26 +1,27 @@ -import * as React from 'react'; +import { FunctionComponent, useRef, useState, useEffect } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; import { DataListWrapModifier } from './DataList'; +import { Tooltip } from '../Tooltip'; export interface DataListCellProps extends Omit<React.HTMLProps<HTMLDivElement>, 'width'> { - /** Content rendered inside the DataList cell */ + /** Content rendered inside the data list cell */ children?: React.ReactNode; - /** Additional classes added to the DataList cell */ + /** Additional classes added to the data list cell */ className?: string; - /** Width (from 1-5) to the DataList cell */ + /** Width (from 1-5) to the data list cell */ width?: 1 | 2 | 3 | 4 | 5; - /** Enables the body Content to fill the height of the card */ + /** Enables the body content to fill the height of the card */ isFilled?: boolean; /** Aligns the cell content to the right of its parent. */ alignRight?: boolean; - /** Set to true if the cell content is an Icon */ + /** Set to true if the cell content is an icon */ isIcon?: boolean; - /** Determines which wrapping modifier to apply to the DataListCell */ + /** Determines which wrapping modifier to apply to the data list cell */ wrapModifier?: DataListWrapModifier | 'nowrap' | 'truncate' | 'breakWord'; } -export const DataListCell: React.FunctionComponent<DataListCellProps> = ({ +export const DataListCell: FunctionComponent<DataListCellProps> = ({ children = null, className = '', width = 1, @@ -29,20 +30,38 @@ export const DataListCell: React.FunctionComponent<DataListCellProps> = ({ isIcon = false, wrapModifier = null, ...props -}: DataListCellProps) => ( - <div - className={css( - styles.dataListCell, - width > 1 && styles.modifiers[`flex_${width}` as 'flex_2' | 'flex_3' | 'flex_4' | 'flex_5'], - !isFilled && styles.modifiers.noFill, - alignRight && styles.modifiers.alignRight, - isIcon && styles.modifiers.icon, - className, - wrapModifier && styles.modifiers[wrapModifier] - )} - {...props} - > - {children} - </div> -); +}: DataListCellProps) => { + const cellRef = useRef(null); + const [isTooltipVisible, setIsTooltipVisible] = useState(false); + + useEffect(() => { + if (!cellRef.current || wrapModifier !== 'truncate') { + return; + } + const showTooltip = cellRef.current && cellRef.current.offsetWidth < cellRef.current.scrollWidth; + if (isTooltipVisible !== showTooltip) { + setIsTooltipVisible(showTooltip); + } + }, [cellRef, wrapModifier, isTooltipVisible]); + + return ( + <div + className={css( + styles.dataListCell, + width > 1 && styles.modifiers[`flex_${width}` as 'flex_2' | 'flex_3' | 'flex_4' | 'flex_5'], + !isFilled && styles.modifiers.noFill, + alignRight && styles.modifiers.alignRight, + isIcon && styles.modifiers.icon, + className, + wrapModifier && styles.modifiers[wrapModifier] + )} + {...(isTooltipVisible && { tabIndex: 0 })} + ref={cellRef} + {...props} + > + {children} + {isTooltipVisible && <Tooltip content={children} triggerRef={cellRef} />} + </div> + ); +}; DataListCell.displayName = 'DataListCell'; diff --git a/packages/react-core/src/components/DataList/DataListCheck.tsx b/packages/react-core/src/components/DataList/DataListCheck.tsx index 07622517090..dd968c8b6da 100644 --- a/packages/react-core/src/components/DataList/DataListCheck.tsx +++ b/packages/react-core/src/components/DataList/DataListCheck.tsx @@ -1,20 +1,34 @@ -import * as React from 'react'; +import { Fragment } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; +import { Checkbox, CheckboxProps } from '../Checkbox'; +import { useSSRSafeId } from '../../helpers'; -export interface DataListCheckProps extends Omit<React.HTMLProps<HTMLInputElement>, 'onChange' | 'checked'> { +export interface DataListCheckProps extends Omit<CheckboxProps, 'ref' | 'id'> { + /** Id of the DataList checkbox. */ + id?: string; /** Additional classes added to the DataList item checkbox */ className?: string; /** Flag to show if the DataList checkbox selection is valid or invalid */ isValid?: boolean; /** Flag to show if the DataList checkbox is disabled */ isDisabled?: boolean; - /** Flag to show if the DataList checkbox is checked */ + /** Flag to show if the DataList checkbox is checked when it is controlled by React state. Both isChecked and checked are valid, + * but only use one. + * To make the DataList checkbox uncontrolled, instead use the defaultChecked prop, but do not use both. + */ isChecked?: boolean; - /** Alternate Flag to show if the DataList checkbox is checked */ + /** Flag to show if the DataList checkbox is checked when it is controlled by React state. Both isChecked and checked are valid, + * but only use one. + * To make the DataList checkbox uncontrolled, instead use the defaultChecked prop, but do not use both. + */ checked?: boolean; + /** Flag to set default value of DataList checkbox when it is uncontrolled by React state. + * To make the DataList checkbox controlled, instead use the isChecked prop, but do not use both. + */ + defaultChecked?: boolean; /** A callback for when the DataList checkbox selection changes */ - onChange?: (checked: boolean, event: React.FormEvent<HTMLInputElement>) => void; + onChange?: (event: React.FormEvent<HTMLInputElement>, checked: boolean) => void; /** Aria-labelledby of the DataList checkbox */ 'aria-labelledby': string; /** Flag to indicate if other controls are used in the DataListItem */ @@ -22,33 +36,38 @@ export interface DataListCheckProps extends Omit<React.HTMLProps<HTMLInputElemen } export const DataListCheck: React.FunctionComponent<DataListCheckProps> = ({ - className = '', - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onChange = (checked: boolean, event: React.FormEvent<HTMLInputElement>) => {}, + id, + className, + onChange, isValid = true, isDisabled = false, - isChecked = null, - checked = null, + isChecked, + checked, + defaultChecked, otherControls = false, ...props }: DataListCheckProps) => { + const randomId = useSSRSafeId(); const check = ( <div className={css(styles.dataListCheck)}> - <input - {...props} - type="checkbox" - onChange={event => onChange(event.currentTarget.checked, event)} + <Checkbox + id={id ?? `datalist-check-${randomId}`} + isChecked={isChecked} + checked={checked} + defaultChecked={defaultChecked} + onChange={onChange} aria-invalid={!isValid} - disabled={isDisabled} - checked={isChecked || checked} + isDisabled={isDisabled} + isLabelWrapped + {...props} /> </div> ); return ( - <React.Fragment> + <Fragment> {!otherControls && <div className={css(styles.dataListItemControl, className)}>{check}</div>} {otherControls && check} - </React.Fragment> + </Fragment> ); }; DataListCheck.displayName = 'DataListCheck'; diff --git a/packages/react-core/src/components/DataList/DataListContent.tsx b/packages/react-core/src/components/DataList/DataListContent.tsx index 28e59ea9c31..e5738d6b686 100644 --- a/packages/react-core/src/components/DataList/DataListContent.tsx +++ b/packages/react-core/src/components/DataList/DataListContent.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; diff --git a/packages/react-core/src/components/DataList/DataListControl.tsx b/packages/react-core/src/components/DataList/DataListControl.tsx index 1a1fa9990fb..b44577d2042 100644 --- a/packages/react-core/src/components/DataList/DataListControl.tsx +++ b/packages/react-core/src/components/DataList/DataListControl.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; diff --git a/packages/react-core/src/components/DataList/DataListDragButton.tsx b/packages/react-core/src/components/DataList/DataListDragButton.tsx index d1b00bf1baf..d24c326a334 100644 --- a/packages/react-core/src/components/DataList/DataListDragButton.tsx +++ b/packages/react-core/src/components/DataList/DataListDragButton.tsx @@ -1,8 +1,6 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; import GripVerticalIcon from '@patternfly/react-icons/dist/esm/icons/grip-vertical-icon'; -import { DataListContext } from './DataList'; export interface DataListDragButtonProps extends React.HTMLProps<HTMLButtonElement> { /** Additional classes added to the drag button */ @@ -18,20 +16,15 @@ export const DataListDragButton: React.FunctionComponent<DataListDragButtonProps isDisabled = false, ...props }: DataListDragButtonProps) => ( - <DataListContext.Consumer> - {({ dragKeyHandler }) => ( - <button - className={css(styles.dataListItemDraggableButton, isDisabled && styles.modifiers.disabled, className)} - onKeyDown={dragKeyHandler} - type="button" - disabled={isDisabled} - {...props} - > - <span className={css(styles.dataListItemDraggableIcon)}> - <GripVerticalIcon /> - </span> - </button> - )} - </DataListContext.Consumer> + <button + className={css(styles.dataListItemDraggableButton, isDisabled && styles.modifiers.disabled, className)} + type="button" + disabled={isDisabled} + {...props} + > + <span className={css(styles.dataListItemDraggableIcon)}> + <GripVerticalIcon /> + </span> + </button> ); DataListDragButton.displayName = 'DataListDragButton'; diff --git a/packages/react-core/src/components/DataList/DataListItem.tsx b/packages/react-core/src/components/DataList/DataListItem.tsx index ed93d89279f..702f4ad9dc4 100644 --- a/packages/react-core/src/components/DataList/DataListItem.tsx +++ b/packages/react-core/src/components/DataList/DataListItem.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; +import { Children, Component, cloneElement, isValidElement } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; +import menuStyles from '@patternfly/react-styles/css/components/Menu/menu'; import { DataListContext } from './DataList'; -import { KeyTypes } from '../Select'; -import { DataListDragButton, DataListDragButtonProps } from './DataListDragButton'; +import { KeyTypes } from '../../helpers/constants'; export interface DataListItemProps extends Omit<React.HTMLProps<HTMLLIElement>, 'children' | 'ref'> { /** Flag to show if the expanded content of the DataList item is visible */ @@ -12,10 +12,12 @@ export interface DataListItemProps extends Omit<React.HTMLProps<HTMLLIElement>, children: React.ReactNode; /** Additional classes added to the DataList item should be either <DataListItemRow> or <DataListContent> */ className?: string; - /** Adds accessible text to the DataList item */ + /** Adds an accessible name to the selectable input if one is rendered */ 'aria-labelledby': string; /** Unique id for the DataList item */ id?: string; + /** Aria label to apply to the selectable input if one is rendered */ + selectableInputAriaLabel?: string; } export interface DataListItemChildProps { @@ -23,26 +25,7 @@ export interface DataListItemChildProps { rowid: string; } -function findDataListDragButton(node: React.ReactNode): React.ReactElement<DataListDragButtonProps> | null { - if (!React.isValidElement(node)) { - return null; - } - if (node.type === DataListDragButton) { - return node as React.ReactElement<DataListDragButtonProps>; - } - if (node.props.children) { - for (const child of React.Children.toArray(node.props.children)) { - const button = findDataListDragButton(child); - if (button) { - return button; - } - } - } - - return null; -} - -export class DataListItem extends React.Component<DataListItemProps> { +class DataListItem extends Component<DataListItemProps> { static displayName = 'DataListItem'; static defaultProps: DataListItemProps = { isExpanded: false, @@ -52,18 +35,18 @@ export class DataListItem extends React.Component<DataListItemProps> { 'aria-labelledby': '' }; render() { - const { children, isExpanded, className, id, 'aria-labelledby': ariaLabelledBy, ...props } = this.props; + const { + children, + isExpanded, + className, + id, + 'aria-labelledby': ariaLabelledBy, + selectableInputAriaLabel, + ...props + } = this.props; return ( <DataListContext.Consumer> - {({ - isSelectable, - selectedDataListItemId, - updateSelectedDataListItem, - isDraggable, - dragStart, - dragEnd, - drop - }) => { + {({ isSelectable, selectedDataListItemId, updateSelectedDataListItem, onSelectableRowChange }) => { const selectDataListItem = (event: React.MouseEvent) => { let target: any = event.target; while (event.currentTarget !== target) { @@ -78,25 +61,32 @@ export class DataListItem extends React.Component<DataListItemProps> { target = target.parentNode; } } - updateSelectedDataListItem(id); + updateSelectedDataListItem(event, id); }; const onKeyDown = (event: React.KeyboardEvent) => { - if (event.key === KeyTypes.Enter) { - updateSelectedDataListItem(id); + if ([KeyTypes.Enter, KeyTypes.Space].includes(event.key)) { + const target: any = event.target as HTMLElement; + + if ( + target.closest(`.${menuStyles.menuItem}`) || + target.parentNode.classList.contains(styles.dataListItemAction) || + target.parentNode.classList.contains(styles.dataListItemControl) + ) { + // check other event handlers are not present. + return; + } + + event.preventDefault(); + updateSelectedDataListItem(event, id); } }; - // We made the DataListDragButton determine if the entire item is draggable instead of - // DataListItem like we should have. - // Recursively search children for the DataListDragButton and see if it's disabled... - const dragButton = findDataListDragButton(children); - const dragProps = isDraggable && { - draggable: dragButton ? !dragButton.props.isDisabled : true, - onDrop: drop, - onDragEnd: dragEnd, - onDragStart: dragStart - }; + const isSelected = selectedDataListItemId === id; + + const selectableInputAriaProps = selectableInputAriaLabel + ? { 'aria-label': selectableInputAriaLabel } + : { 'aria-labelledby': ariaLabelledBy }; return ( <li @@ -104,21 +94,28 @@ export class DataListItem extends React.Component<DataListItemProps> { className={css( styles.dataListItem, isExpanded && styles.modifiers.expanded, - isSelectable && styles.modifiers.selectable, - selectedDataListItemId && selectedDataListItemId === id && styles.modifiers.selected, + isSelectable && styles.modifiers.clickable, + selectedDataListItemId && isSelected && styles.modifiers.selected, className )} - aria-labelledby={ariaLabelledBy} {...(isSelectable && { tabIndex: 0, onClick: selectDataListItem, onKeyDown })} - {...(isSelectable && selectedDataListItemId === id && { 'aria-selected': true })} {...props} - {...dragProps} > - {React.Children.map( + {onSelectableRowChange && ( + <input + className="pf-v6-screen-reader" + type="radio" + checked={isSelected} + onChange={(event) => onSelectableRowChange(event, id)} + tabIndex={-1} + {...selectableInputAriaProps} + /> + )} + {Children.map( children, - child => - React.isValidElement(child) && - React.cloneElement(child as React.ReactElement<any>, { + (child) => + isValidElement(child) && + cloneElement(child as React.ReactElement<any>, { rowid: ariaLabelledBy }) )} @@ -129,3 +126,5 @@ export class DataListItem extends React.Component<DataListItemProps> { ); } } + +export { DataListItem }; diff --git a/packages/react-core/src/components/DataList/DataListItemCells.tsx b/packages/react-core/src/components/DataList/DataListItemCells.tsx index 822eb2a7223..458739f5135 100644 --- a/packages/react-core/src/components/DataList/DataListItemCells.tsx +++ b/packages/react-core/src/components/DataList/DataListItemCells.tsx @@ -1,9 +1,8 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; export interface DataListItemCellsProps extends React.HTMLProps<HTMLDivElement> { - /** Additional classes added to the DataList item Content Wrapper. Children should be one ore more <DataListCell> nodes */ + /** Additional classes added to the data list item content wrapper. Children should be one or more <DataListCell> nodes */ className?: string; /** Array of <DataListCell> nodes that are rendered one after the other. */ dataListCells?: React.ReactNode; diff --git a/packages/react-core/src/components/DataList/DataListItemRow.tsx b/packages/react-core/src/components/DataList/DataListItemRow.tsx index 9de956a8088..39e27829a00 100644 --- a/packages/react-core/src/components/DataList/DataListItemRow.tsx +++ b/packages/react-core/src/components/DataList/DataListItemRow.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { Children, cloneElement, isValidElement } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; import { DataListWrapModifier } from './DataList'; @@ -22,11 +22,11 @@ export const DataListItemRow: React.FunctionComponent<DataListItemRowProps> = ({ ...props }: DataListItemRowProps) => ( <div className={css(styles.dataListItemRow, className, wrapModifier && styles.modifiers[wrapModifier])} {...props}> - {React.Children.map( + {Children.map( children, - child => - React.isValidElement(child) && - React.cloneElement(child as React.ReactElement<any>, { + (child) => + isValidElement(child) && + cloneElement(child as React.ReactElement<any>, { rowid }) )} diff --git a/packages/react-core/src/components/DataList/DataListText.tsx b/packages/react-core/src/components/DataList/DataListText.tsx index 69341f792ea..795db78a857 100644 --- a/packages/react-core/src/components/DataList/DataListText.tsx +++ b/packages/react-core/src/components/DataList/DataListText.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useState } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; import { Tooltip } from '../Tooltip'; @@ -30,7 +30,7 @@ export const DataListText: React.FunctionComponent<DataListTextProps> = ({ }: DataListTextProps) => { const Component = component as any; - const [tooltip, setTooltip] = React.useState(''); + const [tooltip, setTooltip] = useState(''); const onMouseEnter = (event: any) => { if (event.target.offsetWidth < event.target.scrollWidth) { setTooltip(tooltipProp || event.target.innerHTML); diff --git a/packages/react-core/src/components/DataList/DataListToggle.tsx b/packages/react-core/src/components/DataList/DataListToggle.tsx index 8483126bfd7..3b3d31f9e0e 100644 --- a/packages/react-core/src/components/DataList/DataListToggle.tsx +++ b/packages/react-core/src/components/DataList/DataListToggle.tsx @@ -1,24 +1,25 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon'; import styles from '@patternfly/react-styles/css/components/DataList/data-list'; -import { Button, ButtonVariant } from '../Button'; +import { Button, ButtonProps, ButtonVariant } from '../Button'; export interface DataListToggleProps extends React.HTMLProps<HTMLDivElement> { - /** Additional classes added to the DataList cell */ + /** Additional classes added to the data list cell */ className?: string; - /** Flag to show if the expanded content of the DataList item is visible */ + /** Flag to show if the expanded content of the data list item is visible */ isExpanded?: boolean; - /** Identify the DataList toggle number */ + /** Identify the data list toggle number */ id: string; /** Id for the row */ rowid?: string; - /** Adds accessible text to the DataList toggle */ + /** Adds accessible text to the data list toggle */ 'aria-labelledby'?: string; - /** Adds accessible text to the DataList toggle */ + /** Adds accessible text to the data list toggle */ 'aria-label'?: string; /** Allows users of some screen readers to shift focus to the controlled element. Should be used when the controlled contents are not adjacent to the toggle that controls them. */ 'aria-controls'?: string; + /** Additional properties spread to the toggle button */ + buttonProps?: ButtonProps; } export const DataListToggle: React.FunctionComponent<DataListToggleProps> = ({ @@ -28,6 +29,7 @@ export const DataListToggle: React.FunctionComponent<DataListToggleProps> = ({ 'aria-label': ariaLabel = 'Details', rowid = '', id, + buttonProps, ...props }: DataListToggleProps) => ( <div className={css(styles.dataListItemControl, className)} {...props}> @@ -39,11 +41,13 @@ export const DataListToggle: React.FunctionComponent<DataListToggleProps> = ({ aria-label={ariaLabel} aria-labelledby={ariaLabel !== 'Details' ? null : `${rowid} ${id}`} aria-expanded={isExpanded} - > - <div className={css(styles.dataListToggleIcon)}> - <AngleRightIcon /> - </div> - </Button> + {...buttonProps} + icon={ + <div className={css(styles.dataListToggleIcon)}> + <RhMicronsCaretDownIcon /> + </div> + } + /> </div> </div> ); diff --git a/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx index 1595be204a5..0a906791717 100644 --- a/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx @@ -1,223 +1,203 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + import { DataList } from '../DataList'; import { DataListItem } from '../DataListItem'; -import { DataListAction } from '../DataListAction'; -import { DataListCell } from '../DataListCell'; -import { DataListToggle } from '../DataListToggle'; -import { DataListItemCells } from '../DataListItemCells'; import { DataListItemRow } from '../DataListItemRow'; -import { DataListContent } from '../DataListContent'; -import { Button } from '../../Button'; -import { DropdownItem, Dropdown, KebabToggle, DropdownPosition } from '../../Dropdown'; - -describe('DataList', () => { - test('List default', () => { - const view = shallow(<DataList aria-label="this is a simple list" />); - expect(view).toMatchSnapshot(); - }); - test('List compact', () => { - const view = shallow(<DataList aria-label="this is a simple list" isCompact />); - expect(view).toMatchSnapshot(); - }); +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; - describe('DataList variants', () => { - ['none', 'always', 'sm', 'md', 'lg', 'xl', '2xl'].forEach(oneBreakpoint => { - test(`Breakpoint - ${oneBreakpoint}`, () => { - const view = mount( - <DataList aria-label="this is a simple list" gridBreakpoint={oneBreakpoint} /> - ); - expect(view).toMatchSnapshot(); - }); - }); - }); +test('Renders to match snapshot', () => { + const { asFragment } = render(<DataList aria-label="list" />); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with default class ${styles.dataList}`, () => { + render(<DataList aria-label="list" />); + expect(screen.getByLabelText('list')).toHaveClass(styles.dataList); +}); + +test(`Renders with custom class when className is passed`, () => { + render(<DataList aria-label="list" className="custom" />); + expect(screen.getByLabelText('list')).toHaveClass('custom'); +}); + +test(`Renders with spread props`, () => { + render(<DataList aria-label="list" id="test" />); + expect(screen.getByLabelText('list')).toHaveAttribute('id', 'test'); +}); + +test(`Renders with aria-label when aria-label is passed`, () => { + render(<DataList aria-label="list">test</DataList>); + expect(screen.getByText('test')).toHaveAccessibleName('list'); +}); + +test(`Renders ${styles.modifiers.compact} when isCompact = true`, () => { + render(<DataList aria-label="list" isCompact />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.compact); +}); - test('List draggable', () => { - const view = shallow(<DataList aria-label="this is a simple list" isCompact onDragFinish={jest.fn()} />); - expect(view).toMatchSnapshot(); +['nowrap', 'truncate', 'breakWord'].forEach((wrap) => { + test(`Renders with class ${styles.modifiers[wrap]} when wrapModifier = ${wrap} is passed`, () => { + render(<DataList aria-label="list" wrapModifier={wrap as 'nowrap' | 'truncate' | 'breakWord'} />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers[wrap]); }); +}); - test('List', () => { - const view = shallow(<DataList key="list-id-1" className="data-list-custom" aria-label="this is a simple list" />); - expect(view).toMatchSnapshot(); +const gridBreakpointClasses = { + none: styles.modifiers.gridNone, + always: 'pf-m-grid', + sm: styles.modifiers.gridSm, + md: styles.modifiers.gridMd, + lg: styles.modifiers.gridLg, + xl: styles.modifiers.gridXl, + '2xl': styles.modifiers.grid_2xl +}; + +['none', 'always', 'sm', 'md', 'lg', 'xl', '2xl'].forEach((oneBreakpoint) => { + test(`Has breakpoint - ${oneBreakpoint} when gridBreakpoint is passed`, () => { + render(<DataList aria-label="list" gridBreakpoint={oneBreakpoint as any} />); + expect(screen.getByLabelText('list')).toHaveClass(gridBreakpointClasses[oneBreakpoint]); }); +}); + +test(`Renders default class ${styles.dataList}`, () => { + render(<DataList key="list-id-1" aria-label="list" />); + expect(screen.getByLabelText('list')).toHaveClass(styles.dataList); +}); - test('Item default', () => { - const view = shallow( - <DataListItem key="item-id-1" aria-labelledby="item-1"> - test +test('Renders custom class when passed', () => { + render(<DataList key="list-id-1" className="data-list-custom" aria-label="list" />); + expect(screen.getByLabelText('list')).toHaveClass('data-list-custom'); +}); + +test(`Renders with class ${styles.modifiers.plain} when isPlain is true`, () => { + render(<DataList key="list-id-1" isPlain aria-label="list" />); + + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.plain); +}); + +test(`Renders with ${styles.modifiers.noPlainOnGlass} when isNoPlainOnGlass is true`, () => { + render(<DataList aria-label="list" isNoPlainOnGlass />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.noPlainOnGlass); +}); + +test(`Renders with both ${styles.modifiers.plain} and ${styles.modifiers.noPlainOnGlass} when isPlain and isNoPlainOnGlass are true`, () => { + render(<DataList aria-label="list" isPlain isNoPlainOnGlass />); + const list = screen.getByLabelText('list'); + expect(list).toHaveClass(styles.modifiers.plain); + expect(list).toHaveClass(styles.modifiers.noPlainOnGlass); +}); + +test('Renders with a hidden input to improve a11y when onSelectableRowChange is passed', () => { + render( + <DataList aria-label="this is a simple list" onSelectableRowChange={() => {}}> + <DataListItem> + <DataListItemRow aria-labelledby="test-id"> + <p id="test-id">Test</p> + </DataListItemRow> </DataListItem> - ); - expect(view).toMatchSnapshot(); - }); + </DataList> + ); + + const selectableInput = screen.getByRole('radio', { hidden: true }); - test('Item expanded', () => { - const view = mount( - <DataListItem aria-labelledby="item-1" isExpanded> - test + expect(selectableInput).toBeInTheDocument(); +}); + +test('Does not render with a hidden input to improve a11y when onSelectableRowChange is not passed', () => { + render( + <DataList aria-label="this is a simple list"> + <DataListItem> + <DataListItemRow aria-labelledby="test-id"> + <p id="test-id">Test</p> + </DataListItemRow> </DataListItem> - ); - expect(view.find('li').props().className).toBe('pf-c-data-list__item pf-m-expanded'); - }); + </DataList> + ); + + const selectableInput = screen.queryByRole('radio', { hidden: true }); - test('Item', () => { - const view = shallow( - <DataListItem className="data-list-item-custom" aria-labelledby="item-1"> - test + expect(selectableInput).not.toBeInTheDocument(); +}); + +test('Calls onSelectableRowChange when the selectable input changes', async () => { + const mock = jest.fn(); + const user = userEvent.setup(); + + render( + <DataList aria-label="this is a simple list" onSelectableRowChange={mock} selectedDataListItemId=""> + <DataListItem id="item-test-id"> + <DataListItemRow aria-labelledby="test-id"> + <p id="test-id">Test</p> + </DataListItemRow> </DataListItem> - ); - expect(view).toMatchSnapshot(); - }); + </DataList> + ); - test('item row default', () => { - const view = shallow(<DataListItemRow>test</DataListItemRow>); - expect(view).toMatchSnapshot(); - }); + const selectableInput = screen.getByRole('radio', { hidden: true }); + await user.click(selectableInput); - test('Cell default', () => { - const view = shallow(<DataListCell>Secondary</DataListCell>); - expect(view).toMatchSnapshot(); - }); + expect(mock).toHaveBeenCalled(); +}); - test('Cells', () => { - const view = shallow( - <DataListItemCells - dataListCells={[ - <DataListCell key="list-id-1" id="primary-item" className="data-list-custom"> - Primary Id - </DataListCell>, - <DataListCell key="list-id-2" id="primary-item" className="data-list-custom"> - Primary Id 2 - </DataListCell> - ]} - /> - ); - expect(view).toMatchSnapshot(); - }); +test('Does not call onSelectableRowChange when the selectable input is not changed', () => { + const mock = jest.fn(); - test('Cell with width modifier', () => { - [ - { width: 1 as const, class: '' }, - { width: 2 as const, class: 'pf-m-flex-2' }, - { width: 3 as const, class: 'pf-m-flex-3' }, - { width: 4 as const, class: 'pf-m-flex-4' }, - { width: 5 as const, class: 'pf-m-flex-5' } - ].forEach(testCase => { - const view = shallow( - <DataListCell width={testCase.width} key="list-id-1" id="primary-item"> - Primary Id - </DataListCell> - ); - testCase.class === '' - ? expect(view.props().className).toBe('pf-c-data-list__cell') - : expect(view.props().className).toBe(`pf-c-data-list__cell ${testCase.class}`); - }); - }); + render( + <DataList aria-label="this is a simple list" onSelectableRowChange={mock} selectedDataListItemId=""> + <DataListItem id="item-test-id"> + <DataListItemRow aria-labelledby="test-id"> + <p id="test-id">Test</p> + </DataListItemRow> + </DataListItem> + </DataList> + ); - test('Cell with text modifiers', () => { - [ - { wrapModifier: null as const, class: '' }, - { wrapModifier: 'breakWord' as const, class: 'pf-m-break-word' }, - { wrapModifier: 'nowrap' as const, class: 'pf-m-nowrap' }, - { wrapModifier: 'truncate' as const, class: 'pf-m-truncate' }, - ].forEach(testCase => { - const view = shallow( - <DataListCell wrapModifier={testCase.wrapModifier} key="list-id-1" id="primary-item"> - Primary Id - </DataListCell> - ); - testCase.class === '' - ? expect(view.props().className).toBe('pf-c-data-list__cell') - : expect(view.props().className).toBe(`pf-c-data-list__cell ${testCase.class}`); - }); - }); + expect(mock).not.toHaveBeenCalled(); +}); - test('Toggle default with aria label', () => { - const view = shallow(<DataListToggle aria-label="Toggle details for" id="ex-toggle2" />); +test('Applies selectableInputAriaLabel to the hidden input', () => { + render( + <DataList aria-label="this is a simple list" onSelectableRowChange={() => {}}> + <DataListItem selectableInputAriaLabel="Data list item label test"> + <DataListItemRow aria-labelledby="test-id"> + <p id="test-id">Test</p> + </DataListItemRow> + </DataListItem> + </DataList> + ); - expect(view.find(Button).props()['aria-label']).toBe('Toggle details for'); - expect(view.find(Button).props()['aria-labelledby']).toBe(null); - expect(view.find(Button).props()['aria-expanded']).toBe(false); - expect(view.find(Button).props().id).toBe('ex-toggle2'); - expect(view.find(Button).props().id).toBe('ex-toggle2'); - }); + const selectableInput = screen.getByRole('radio', { hidden: true }); - test('Toggle expanded', () => { - const view = shallow(<DataListToggle aria-label="Toggle details for" id="ex-toggle2" isExpanded />); - expect(view.find(Button).props()['aria-expanded']).toBe(true); - }); + expect(selectableInput).toHaveAccessibleName('Data list item label test'); +}); - test('DataListAction dropdown', () => { - const view = shallow( - <DataListAction aria-label="Actions" aria-labelledby="ex-action" id="ex-action" isPlainButtonAction> - <Dropdown - isPlain - position={DropdownPosition.right} - toggle={<KebabToggle />} - dropdownItems={[ - <DropdownItem component="button" onClick={jest.fn()} key="action-1"> - action-1 - </DropdownItem>, - <DropdownItem component="button" onClick={jest.fn()} key="action-2"> - action-2 - </DropdownItem> - ]} - /> - </DataListAction> - ); - expect(view).toMatchSnapshot(); - }); +test('Defaults to labelling its input using its aria-labelledby prop', () => { + render( + <DataList aria-label="this is a simple list" onSelectableRowChange={() => {}}> + <DataListItem aria-labelledby="test-id"> + <p id="test-id">Test cell content</p> + </DataListItem> + </DataList> + ); - test('DataListAction button', () => { - const view = shallow( - <DataListAction aria-label="Actions" aria-labelledby="ex-action" id="ex-action"> - <Button id="delete-item-1">Delete</Button> - </DataListAction> - ); - expect(view).toMatchSnapshot(); - }); + const selectableInput = screen.getByRole('radio', { hidden: true }); - test('DataListAction visibility - show button when lg', () => { - const view = shallow( - <DataListAction - visibility={{ default: 'hidden', lg: 'visible' }} - aria-labelledby="check-action-item2 check-action-action2" - id="check-action-action2" - aria-label="Actions" - > - <Button variant="primary">Primary</Button> - </DataListAction> - ); - expect(view.find('div').props().className).toContain('pf-m-hidden'); - expect(view.find('div').props().className).toContain('pf-m-visible-on-lg'); - }); + expect(selectableInput).toHaveAccessibleName('Test cell content'); +}); - test('DataListAction visibility - hide button on 2xl', () => { - const view = shallow( - <DataListAction - visibility={{ '2xl': 'hidden' }} - aria-labelledby="check-action-item2 check-action-action2" - id="check-action-action2" - aria-label="Actions" - > - <Button variant="primary">Primary</Button> - </DataListAction> - ); - expect(view.find('div').props().className).toContain('pf-m-hidden-on-2xl'); - }); +test('Prioritizes selectableInputAriaLabel over aria-labelledby prop', () => { + render( + <DataList aria-label="this is a simple list" onSelectableRowChange={() => {}}> + <DataListItem aria-labelledby="test-id" selectableInputAriaLabel="Data list item label test"> + <p id="test-id">Test cell content</p> + </DataListItem> + </DataList> + ); - test('DataListContent', () => { - const view = shallow(<DataListContent aria-label="Primary Content Details"> test</DataListContent>); - expect(view).toMatchSnapshot(); - }); + const selectableInput = screen.getByRole('radio', { hidden: true }); - test('DataListContent hasNoPadding', () => { - const view = shallow( - <DataListContent aria-label="Primary Content Details" hidden hasNoPadding> - test - </DataListContent> - ); - expect(view).toMatchSnapshot(); - }); + expect(selectableInput).toHaveAccessibleName('Data list item label test'); }); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListAction.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListAction.test.tsx new file mode 100644 index 00000000000..c6dbaf99c9c --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListAction.test.tsx @@ -0,0 +1,74 @@ +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; + +import { DataListAction } from '../DataListAction'; + +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render( + <DataListAction aria-label="Actions" aria-labelledby="ex-action" id="ex-action"> + test + </DataListAction> + ); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with default class ${styles.dataListItemAction}`, () => { + render( + <DataListAction aria-label="Actions" data-testid="actions" aria-labelledby="ex-action" id="ex-action"> + test + </DataListAction> + ); + expect(screen.getByTestId('actions')).toHaveClass(styles.dataListItemAction, { exact: true }); +}); + +test(`Renders with custom class when className is passed`, () => { + render( + <DataListAction + aria-label="Actions" + data-testid="actions" + aria-labelledby="ex-action" + id="ex-action" + className="test-class" + > + test + </DataListAction> + ); + expect(screen.getByTestId('actions')).toHaveClass('test-class'); +}); + +test(`Renders with spread props`, () => { + render( + <DataListAction dir="rtl" data-testid="actions" aria-label="Actions" aria-labelledby="ex-action" id="ex-action"> + test + </DataListAction> + ); + expect(screen.getByTestId('actions')).toHaveAttribute('dir', 'rtl'); +}); + +['hidden', 'visible'].forEach((vis) => { + const visMod = vis as 'hidden' | 'visible'; + test(`Has visibility - ${vis} for every breakpoint`, () => { + render( + <DataListAction + visibility={{ default: visMod, sm: visMod, md: visMod, lg: visMod, xl: visMod, '2xl': visMod }} + aria-labelledby="check-action-item2 check-action-action2" + id="check-action-action2" + aria-label="Actions" + data-testid="actions" + > + test + </DataListAction> + ); + + if (visMod === 'hidden') { + expect(screen.getByTestId('actions')).toHaveClass(styles.modifiers[`${visMod}`]); + } + expect(screen.getByTestId('actions')).toHaveClass(styles.modifiers[`${visMod}OnSm`]); + expect(screen.getByTestId('actions')).toHaveClass(styles.modifiers[`${visMod}OnMd`]); + expect(screen.getByTestId('actions')).toHaveClass(styles.modifiers[`${visMod}OnLg`]); + expect(screen.getByTestId('actions')).toHaveClass(styles.modifiers[`${visMod}OnXl`]); + expect(screen.getByTestId('actions')).toHaveClass(styles.modifiers[`${visMod}On_2xl`]); + }); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListCell.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListCell.test.tsx new file mode 100644 index 00000000000..36a55cbc3e6 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListCell.test.tsx @@ -0,0 +1,119 @@ +import { render, screen } from '@testing-library/react'; +import { DataListCell } from '../DataListCell'; + +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; + +test('Cell renders to match snapshot', () => { + const { asFragment } = render(<DataListCell>Secondary</DataListCell>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders default class ${styles.dataListCell}`, () => { + render( + <DataListCell data-testid="test" key={0}> + Primary Id + </DataListCell> + ); + expect(screen.getByTestId('test')).toHaveClass(styles.dataListCell, { exact: true }); +}); + +test(`Renders custom class when className is passed`, () => { + render( + <DataListCell data-testid="test" key={0} className="test-class"> + Primary Id + </DataListCell> + ); + expect(screen.getByTestId('test')).toHaveClass('test-class'); +}); + +test(`Renders with spread props`, () => { + render( + <DataListCell key={0} id="test"> + Primary Id + </DataListCell> + ); + expect(screen.getByText('Primary Id')).toHaveAttribute('id', 'test'); +}); + +test('Renders width modifier when width is passed', () => { + [ + { width: 1, class: '' }, + { width: 2, class: styles.modifiers.flex_2 }, + { width: 3, class: styles.modifiers.flex_3 }, + { width: 4, class: styles.modifiers.flex_4 }, + { width: 5, class: styles.modifiers.flex_5 } + ].forEach((testCase, index) => { + const testId = `cell-test-id-${index}`; + + render( + <DataListCell data-testid={testId} width={testCase.width as any} key={index}> + Primary Id + </DataListCell> + ); + + const dataListCell = screen.getByTestId(testId); + + testCase.class === '' + ? expect(dataListCell).not.toHaveClass( + styles.modifiers.flex_2, + styles.modifiers.flex_3, + styles.modifiers.flex_4, + styles.modifiers.flex_5 + ) + : expect(dataListCell).toHaveClass(`pf-v6-c-data-list__cell ${testCase.class}`, { exact: true }); + }); +}); + +test('Has text wrap modifiers when wrapModifier is passed', () => { + [ + { wrapModifier: null as any, class: '' }, + { wrapModifier: 'breakWord', class: styles.modifiers.breakWord }, + { wrapModifier: 'nowrap', class: styles.modifiers.nowrap }, + { wrapModifier: 'truncate', class: styles.modifiers.truncate } + ].forEach((testCase, index) => { + const testId = `cell-test-id-${index}`; + + render( + <DataListCell data-testid={testId} wrapModifier={testCase.wrapModifier} key={index}> + Primary Id + </DataListCell> + ); + + const dataListCell = screen.getByTestId(testId); + + testCase.class === '' + ? expect(dataListCell).not.toHaveClass( + styles.modifiers.breakWord, + styles.modifiers.nowrap, + styles.modifiers.truncate + ) + : expect(dataListCell).toHaveClass(`${testCase.class}`); + }); +}); + +test(`Renders with class ${styles.modifiers.alignRight} when alignRight is passed`, () => { + render( + <DataListCell data-testid="test" key={0} alignRight> + Primary Id + </DataListCell> + ); + expect(screen.getByTestId('test')).toHaveClass(styles.modifiers.alignRight); +}); + +test(`Renders with class ${styles.modifiers.icon} when isIcon is passed`, () => { + render( + <DataListCell data-testid="test" key={0} isIcon> + Primary Id + </DataListCell> + ); + expect(screen.getByTestId('test')).toHaveClass(styles.modifiers.icon); +}); + +test(`Renders with class ${styles.modifiers.noFill} when isFilled = false`, () => { + render( + <DataListCell data-testid="test" key={0} isFilled={false}> + Primary Id + </DataListCell> + ); + expect(screen.getByTestId('test')).toHaveClass(styles.modifiers.noFill); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListCheck.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListCheck.test.tsx new file mode 100644 index 00000000000..eff217f7f22 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListCheck.test.tsx @@ -0,0 +1,28 @@ +import { useState } from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { DataListCheck } from '../DataListCheck'; + +test(`Renders with spread props`, () => { + render(<DataListCheck id="test" aria-labelledby={'string'} isChecked />); + expect(screen.getByRole('checkbox')).toHaveAttribute('id', 'test'); +}); + +it('does not throw a "A component is changing an uncontrolled input of type checkbox to be controlled" error when changed if using isChecked', async () => { + const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const user = userEvent.setup(); + + const ControlledDataListCheck = () => { + const [checked, setChecked] = useState(false); + + return ( + <DataListCheck id="test" isChecked={checked} onChange={() => setChecked(!checked)} aria-labelledby={'string'} /> + ); + }; + + render(<ControlledDataListCheck />); + + await user.click(screen.getByRole('checkbox')); + + expect(consoleSpy).not.toHaveBeenCalled(); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListContent.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListContent.test.tsx new file mode 100644 index 00000000000..63506fb6184 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListContent.test.tsx @@ -0,0 +1,72 @@ +import { render, screen } from '@testing-library/react'; +import { DataListContent } from '../DataListContent'; + +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render(<DataListContent aria-label="Primary Content Details"> test</DataListContent>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with default class ${styles.dataListExpandableContent}`, () => { + render( + <DataListContent data-testid="test-id" aria-label="Primary Content Details"> + test + </DataListContent> + ); + expect(screen.getByTestId('test-id')).toHaveClass(styles.dataListExpandableContent, { exact: true }); +}); + +test(`Renders with default class ${styles.dataListExpandableContentBody}`, () => { + render( + <DataListContent data-testid="test-id" aria-label="Primary Content Details"> + test + </DataListContent> + ); + expect(screen.getByText('test')).toHaveClass(styles.dataListExpandableContentBody, { exact: true }); +}); + +test(`Renders with custom class when className is passed`, () => { + render( + <DataListContent data-testid="test-id" aria-label="Primary Content Details" className="test-class"> + test + </DataListContent> + ); + expect(screen.getByTestId('test-id')).toHaveClass('test-class'); +}); + +test(`Renders with id when id is passed`, () => { + render( + <DataListContent id="idProp" data-testid="test-id" aria-label="Primary Content Details" className="test-class"> + test + </DataListContent> + ); + expect(screen.getByTestId('test-id')).toHaveAttribute('id', 'idProp'); +}); + +test(`Renders with spread props`, () => { + render( + <DataListContent dir="rtl" data-testid="test-id" aria-label="Primary Content Details"> + test + </DataListContent> + ); + expect(screen.getByTestId('test-id')).toHaveAttribute('dir', 'rtl'); +}); + +test(`Renders with class ${styles.modifiers.noPadding} when hasNoPadding is passed`, () => { + render( + <DataListContent aria-label="Primary Content Details" hidden hasNoPadding> + test + </DataListContent> + ); + expect(screen.getByText('test')).toHaveClass(styles.modifiers.noPadding); +}); + +test(`Renders with hidden property when isHidden is passed`, () => { + render( + <DataListContent data-testid="test-id" aria-label="Primary Content Details" isHidden> + test + </DataListContent> + ); + expect(screen.getByTestId('test-id')).toHaveAttribute('hidden'); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListItem.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListItem.test.tsx new file mode 100644 index 00000000000..19b0fb2d5da --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListItem.test.tsx @@ -0,0 +1,45 @@ +import { render, screen } from '@testing-library/react'; +import { DataListItem } from '../DataListItem'; + +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render( + <DataListItem key="item-id-1" aria-labelledby="item-1"> + test + </DataListItem> + ); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with default class ${styles.dataListItem}`, () => { + render(<DataListItem aria-labelledby="item-1">test</DataListItem>); + expect(screen.getByRole('listitem')).toHaveClass(styles.dataListItem, { exact: true }); +}); + +test('Renders with custom class name', () => { + render( + <DataListItem className="data-list-item-custom" aria-labelledby="item-1"> + test + </DataListItem> + ); + expect(screen.getByRole('listitem')).toHaveClass('data-list-item-custom'); +}); + +test('Renders with spread props', () => { + render( + <DataListItem dir="rtl" aria-labelledby="item-1"> + test + </DataListItem> + ); + expect(screen.getByRole('listitem')).toHaveAttribute('dir', 'rtl'); +}); + +test(`Renders class ${styles.modifiers.expanded} when isExpanded is passed`, () => { + render( + <DataListItem aria-labelledby="item-1" isExpanded> + test + </DataListItem> + ); + expect(screen.getByRole('listitem')).toHaveClass(styles.modifiers.expanded); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListItemCells.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListItemCells.test.tsx new file mode 100644 index 00000000000..c8d756b1985 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListItemCells.test.tsx @@ -0,0 +1,24 @@ +import { render, screen } from '@testing-library/react'; +import { DataListItemCells } from '../DataListItemCells'; + +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; + +test('Cells renders to match snapshot', () => { + const { asFragment } = render(<DataListItemCells dataListCells={[]} />); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with default class ${styles.dataListItemContent}`, () => { + render(<DataListItemCells dataListCells="test" />); + expect(screen.getByText('test')).toHaveClass(styles.dataListItemContent, { exact: true }); +}); + +test(`Renders with custom class when className is passed`, () => { + render(<DataListItemCells className="custom" dataListCells="test" />); + expect(screen.getByText('test')).toHaveClass('custom'); +}); + +test(`Renders with spread props`, () => { + render(<DataListItemCells dir="rtl" dataListCells="test" />); + expect(screen.getByText('test')).toHaveAttribute('dir', 'rtl'); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListItemRow.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListItemRow.test.tsx new file mode 100644 index 00000000000..e86ec190661 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListItemRow.test.tsx @@ -0,0 +1,43 @@ +import { render, screen } from '@testing-library/react'; +import { DataListItemRow } from '../DataListItemRow'; + +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; + +test('Item row renders to match snapshot', () => { + const { asFragment } = render(<DataListItemRow>test</DataListItemRow>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with default class ${styles.dataListItemRow}`, () => { + render(<DataListItemRow data-testid="test">test</DataListItemRow>); + expect(screen.getByTestId('test')).toHaveClass(styles.dataListItemRow, { exact: true }); +}); + +test(`Renders with custom class when className is passed`, () => { + render( + <DataListItemRow className="custom" data-testid="test"> + test + </DataListItemRow> + ); + expect(screen.getByTestId('test')).toHaveClass('custom'); +}); + +test(`Renders with spread props`, () => { + render( + <DataListItemRow dir="rtl" data-testid="test"> + test + </DataListItemRow> + ); + expect(screen.getByTestId('test')).toHaveAttribute('dir', 'rtl'); +}); + +['nowrap', 'truncate', 'breakWord'].forEach((wrap) => { + test(`Renders with class ${styles.modifiers[wrap]} when wrapModifier = ${wrap} is passed`, () => { + render( + <DataListItemRow data-testid="test" wrapModifier={wrap as 'nowrap' | 'truncate' | 'breakWord'}> + test + </DataListItemRow> + ); + expect(screen.getByTestId('test')).toHaveClass(styles.modifiers[wrap]); + }); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListToggle.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListToggle.test.tsx new file mode 100644 index 00000000000..af677b320b3 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/DataListToggle.test.tsx @@ -0,0 +1,60 @@ +import { render, screen } from '@testing-library/react'; +import { DataListToggle } from '../DataListToggle'; + +import styles from '@patternfly/react-styles/css/components/DataList/data-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render(<DataListToggle id="ex-toggle2" />); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders with default class ${styles.dataListToggle}`, () => { + render(<DataListToggle id="ex-toggle2" />); + expect(screen.getByRole('button').parentElement).toHaveClass(styles.dataListToggle); +}); + +test(`Renders with default class ${styles.dataListItemControl}`, () => { + render(<DataListToggle id="ex-toggle2" />); + expect(screen.getByRole('button').parentElement?.parentElement).toHaveClass(styles.dataListItemControl, { + exact: true + }); +}); + +test(`Renders with custom class when className is passed`, () => { + render(<DataListToggle className="custom" id="ex-toggle2" />); + expect(screen.getByRole('button').parentElement?.parentElement).toHaveClass('custom'); +}); + +test(`Renders with spread props`, () => { + render(<DataListToggle dir="rtl" id="ex-toggle2" />); + expect(screen.getByRole('button').parentElement?.parentElement).toHaveAttribute('dir', 'rtl'); +}); + +test(`Renders with spread buttonProps`, () => { + render(<DataListToggle buttonProps={{ isDisabled: true }} id="ex-toggle2" />); + expect(screen.getByRole('button')).toHaveAttribute('disabled'); +}); + +test('Renders aria-labelledby by default when no custom aria-label is passed', () => { + render(<DataListToggle rowid="row" id="ex-toggle2" />); + + expect(screen.getByRole('button')).toHaveAttribute('aria-labelledby', 'row ex-toggle2'); +}); + +test('Does not render aria-labelledby when custom aria-label is passed', () => { + render(<DataListToggle aria-label="Toggle details for" id="ex-toggle2" />); + + expect(screen.getByRole('button')).not.toHaveAttribute('aria-labelledby'); + expect(screen.getByRole('button')).toHaveAccessibleName('Toggle details for'); +}); + +test(`Renders with ariaControls when ariaControls is passed`, () => { + render(<DataListToggle aria-controls="control" id="ex-toggle2" />); + expect(screen.getByRole('button')).toHaveAttribute('aria-controls', 'control'); +}); + +test('Renders with aria-expanded when isExpanded = true', () => { + render(<DataListToggle isExpanded id="ex-toggle2" />); + + expect(screen.getByRole('button')).toHaveAttribute('aria-expanded', 'true'); +}); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataList.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataList.test.tsx deleted file mode 100644 index 68ff65da720..00000000000 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataList.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DataList } from '../../DataList'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DataList should match snapshot (auto-generated)', () => { - const view = shallow( - <DataList - children={<>ReactNode</>} - className={"''"} - aria-label={'string'} - onSelectDataListItem={(id: string) => undefined as void} - selectedDataListItemId={"''"} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListAction.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListAction.test.tsx index 6080a526636..d6af1889bfe 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListAction.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListAction.test.tsx @@ -1,14 +1,13 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListAction } from '../../DataListAction'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListAction should match snapshot (auto-generated)', () => { - const view = shallow( + const { asFragment } = render( <DataListAction children={<div>ReactNode</div>} className={"''"} @@ -17,5 +16,5 @@ it('DataListAction should match snapshot (auto-generated)', () => { aria-label={'string'} /> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListCell.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListCell.test.tsx index 0c2773d606e..9325da25c76 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListCell.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListCell.test.tsx @@ -1,14 +1,13 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListCell } from '../../DataListCell'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListCell should match snapshot (auto-generated)', () => { - const view = shallow( + const { asFragment } = render( <DataListCell children={<>ReactNode</>} className={"''"} @@ -18,5 +17,5 @@ it('DataListCell should match snapshot (auto-generated)', () => { isIcon={false} /> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListCheck.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListCheck.test.tsx index 03a527fc725..81c1612e8b3 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListCheck.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListCheck.test.tsx @@ -1,23 +1,23 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListCheck } from '../../DataListCheck'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListCheck should match snapshot (auto-generated)', () => { - const view = shallow( + const { asFragment } = render( <DataListCheck + id="test" className={"''"} isValid={true} isDisabled={false} - isChecked={null} - checked={null} - onChange={(checked: boolean, event: React.FormEvent<HTMLInputElement>) => {}} + isChecked={false} + checked={false} + onChange={(event: React.FormEvent<HTMLInputElement>, checked: boolean) => {}} aria-labelledby={'string'} /> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListContent.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListContent.test.tsx index 539a6001784..d56ee15d68e 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListContent.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListContent.test.tsx @@ -1,14 +1,13 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListContent } from '../../DataListContent'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListContent should match snapshot (auto-generated)', () => { - const view = shallow( + const { asFragment } = render( <DataListContent children={<>ReactNode</>} className={"''"} @@ -19,5 +18,5 @@ it('DataListContent should match snapshot (auto-generated)', () => { aria-label={'string'} /> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListItem.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListItem.test.tsx index 08a682f53c2..8ce3d07a96a 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListItem.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListItem.test.tsx @@ -1,14 +1,13 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListItem } from '../../DataListItem'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListItem should match snapshot (auto-generated)', () => { - const view = shallow( + const { asFragment } = render( <DataListItem isExpanded={false} children={<div>ReactNode</div>} @@ -17,5 +16,5 @@ it('DataListItem should match snapshot (auto-generated)', () => { id={"''"} /> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemCells.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemCells.test.tsx index 7de1d235d57..67438001e56 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemCells.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemCells.test.tsx @@ -1,13 +1,14 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListItemCells } from '../../DataListItemCells'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListItemCells should match snapshot (auto-generated)', () => { - const view = shallow(<DataListItemCells className={"''"} dataListCells={<div>ReactNode</div>} rowid={"''"} />); - expect(view).toMatchSnapshot(); + const { asFragment } = render( + <DataListItemCells className={"''"} dataListCells={<div>ReactNode</div>} rowid={"''"} /> + ); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemRow.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemRow.test.tsx index 3ab2e09d590..6179c72efde 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemRow.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListItemRow.test.tsx @@ -1,13 +1,12 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListItemRow } from '../../DataListItemRow'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListItemRow should match snapshot (auto-generated)', () => { - const view = shallow(<DataListItemRow children={<div>ReactNode</div>} className={"''"} rowid={"''"} />); - expect(view).toMatchSnapshot(); + const { asFragment } = render(<DataListItemRow children={<div>ReactNode</div>} className={"''"} rowid={"''"} />); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/DataListToggle.test.tsx b/packages/react-core/src/components/DataList/__tests__/Generated/DataListToggle.test.tsx index e0149e9cc80..e6fff7d3fbf 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/DataListToggle.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/Generated/DataListToggle.test.tsx @@ -1,14 +1,13 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DataListToggle } from '../../DataListToggle'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DataListToggle should match snapshot (auto-generated)', () => { - const view = shallow( + const { asFragment } = render( <DataListToggle className={"''"} isExpanded={false} @@ -19,5 +18,5 @@ it('DataListToggle should match snapshot (auto-generated)', () => { aria-controls={"''"} /> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataList.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataList.test.tsx.snap deleted file mode 100644 index 8f25c2bb31d..00000000000 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataList.test.tsx.snap +++ /dev/null @@ -1,25 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DataList should match snapshot (auto-generated) 1`] = ` -<ContextProvider - value={ - Object { - "dragEnd": [Function], - "dragKeyHandler": [Function], - "dragStart": [Function], - "drop": [Function], - "isDraggable": false, - "isSelectable": true, - "selectedDataListItemId": "''", - "updateSelectedDataListItem": [Function], - } - } -> - <ul - aria-label="string" - className="pf-c-data-list pf-m-grid-md ''" - > - ReactNode - </ul> -</ContextProvider> -`; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListAction.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListAction.test.tsx.snap index c39d1c0e3f3..1a518f99938 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListAction.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListAction.test.tsx.snap @@ -1,11 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListAction should match snapshot (auto-generated) 1`] = ` -<div - className="pf-c-data-list__item-action ''" -> - <div> - ReactNode +<DocumentFragment> + <div + class="pf-v6-c-data-list__item-action ''" + > + <div> + ReactNode + </div> </div> -</div> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCell.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCell.test.tsx.snap index 57c5393acb0..1bc2b83e0ad 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCell.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCell.test.tsx.snap @@ -1,9 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListCell should match snapshot (auto-generated) 1`] = ` -<div - className="pf-c-data-list__cell ''" -> - ReactNode -</div> +<DocumentFragment> + <div + class="pf-v6-c-data-list__cell ''" + > + ReactNode + </div> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCheck.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCheck.test.tsx.snap index 5d5db286c1f..111df143cec 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCheck.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListCheck.test.tsx.snap @@ -1,22 +1,29 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListCheck should match snapshot (auto-generated) 1`] = ` -<Fragment> +<DocumentFragment> <div - className="pf-c-data-list__item-control ''" + class="pf-v6-c-data-list__item-control ''" > <div - className="pf-c-data-list__check" + class="pf-v6-c-data-list__check" > - <input - aria-invalid={false} - aria-labelledby="string" - checked={null} - disabled={false} - onChange={[Function]} - type="checkbox" - /> + <label + class="pf-v6-c-check pf-m-standalone" + for="test" + > + <input + aria-invalid="false" + aria-labelledby="string" + class="pf-v6-c-check__input" + data-ouia-component-id="OUIA-Generated-Checkbox-:r2:" + data-ouia-component-type="PF6/Checkbox" + data-ouia-safe="true" + id="test" + type="checkbox" + /> + </label> </div> </div> -</Fragment> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListContent.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListContent.test.tsx.snap index fec4344e715..566a5a6d940 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListContent.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListContent.test.tsx.snap @@ -1,16 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListContent should match snapshot (auto-generated) 1`] = ` -<section - aria-label="string" - className="pf-c-data-list__expandable-content ''" - hidden={false} - id="''" -> - <div - className="pf-c-data-list__expandable-content-body" +<DocumentFragment> + <section + aria-label="string" + class="pf-v6-c-data-list__expandable-content ''" + id="''" > - ReactNode - </div> -</section> + <div + class="pf-v6-c-data-list__expandable-content-body" + > + ReactNode + </div> + </section> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItem.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItem.test.tsx.snap index e62b4d2238e..02554c4686b 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItem.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItem.test.tsx.snap @@ -1,7 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListItem should match snapshot (auto-generated) 1`] = ` -<ContextConsumer> - <Component /> -</ContextConsumer> +<DocumentFragment> + <li + class="pf-v6-c-data-list__item ''" + id="''" + > + <div + rowid="string" + > + ReactNode + </div> + </li> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemCells.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemCells.test.tsx.snap index 44f4077f864..825924b44b8 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemCells.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemCells.test.tsx.snap @@ -1,11 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListItemCells should match snapshot (auto-generated) 1`] = ` -<div - className="pf-c-data-list__item-content ''" -> - <div> - ReactNode +<DocumentFragment> + <div + class="pf-v6-c-data-list__item-content ''" + > + <div> + ReactNode + </div> </div> -</div> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemRow.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemRow.test.tsx.snap index 0095a4761fb..b6bf0232aac 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemRow.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListItemRow.test.tsx.snap @@ -1,14 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListItemRow should match snapshot (auto-generated) 1`] = ` -<div - className="pf-c-data-list__item-row ''" -> +<DocumentFragment> <div - key=".0" - rowid="''" + class="pf-v6-c-data-list__item-row ''" > - ReactNode + <div + rowid="''" + > + ReactNode + </div> </div> -</div> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListToggle.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListToggle.test.tsx.snap index 234eab582f3..da7429404bb 100644 --- a/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListToggle.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/Generated/__snapshots__/DataListToggle.test.tsx.snap @@ -1,31 +1,48 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DataListToggle should match snapshot (auto-generated) 1`] = ` -<div - aria-labelledby="''" - className="pf-c-data-list__item-control ''" -> +<DocumentFragment> <div - className="pf-c-data-list__toggle" + aria-labelledby="''" + class="pf-v6-c-data-list__item-control ''" > - <Button - aria-controls="''" - aria-expanded={false} - aria-label="'Details'" - aria-labelledby={null} - id="string" - variant="plain" + <div + class="pf-v6-c-data-list__toggle" > - <div - className="pf-c-data-list__toggle-icon" + <button + aria-controls="''" + aria-expanded="false" + aria-label="'Details'" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:r0:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + id="string" + type="button" > - <AngleRightIcon - color="currentColor" - noVerticalAlign={false} - size="sm" - /> - </div> - </Button> + <span + class="pf-v6-c-button__icon" + > + <div + class="pf-v6-c-data-list__toggle-icon" + > + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" + > + <path + d="M18.71 5.29a.996.996 0 0 0-1.41 0l-7.29 7.29-7.3-7.29a.987.987 0 0 0-1.41-.02.987.987 0 0 0-.02 1.41l.02.02 7.65 7.65c.29.29.68.44 1.06.44s.77-.15 1.06-.44l7.65-7.65a.996.996 0 0 0 0-1.41Z" + /> + </svg> + </div> + </span> + </button> + </div> </div> -</div> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataList.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataList.test.tsx.snap index 8683cdb90cf..12ecd984502 100644 --- a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataList.test.tsx.snap +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataList.test.tsx.snap @@ -1,325 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`DataList Cell default 1`] = ` -<div - className="pf-c-data-list__cell" -> - Secondary -</div> -`; - -exports[`DataList Cells 1`] = ` -<div - className="pf-c-data-list__item-content" -> - <DataListCell - className="data-list-custom" - id="primary-item" - key="list-id-1" - > - Primary Id - </DataListCell> - <DataListCell - className="data-list-custom" - id="primary-item" - key="list-id-2" - > - Primary Id 2 - </DataListCell> -</div> -`; - -exports[`DataList DataList variants Breakpoint - 2xl 1`] = ` -<DataList - aria-label="this is a simple list" - className="" - gridBreakpoint="2xl" - isCompact={false} - selectedDataListItemId="" - wrapModifier={null} -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-2xl" - /> -</DataList> -`; - -exports[`DataList DataList variants Breakpoint - always 1`] = ` -<DataList - aria-label="this is a simple list" - className="" - gridBreakpoint="always" - isCompact={false} - selectedDataListItemId="" - wrapModifier={null} -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid" - /> -</DataList> -`; - -exports[`DataList DataList variants Breakpoint - lg 1`] = ` -<DataList - aria-label="this is a simple list" - className="" - gridBreakpoint="lg" - isCompact={false} - selectedDataListItemId="" - wrapModifier={null} -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-lg" - /> -</DataList> -`; - -exports[`DataList DataList variants Breakpoint - md 1`] = ` -<DataList - aria-label="this is a simple list" - className="" - gridBreakpoint="md" - isCompact={false} - selectedDataListItemId="" - wrapModifier={null} -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-md" - /> -</DataList> -`; - -exports[`DataList DataList variants Breakpoint - none 1`] = ` -<DataList - aria-label="this is a simple list" - className="" - gridBreakpoint="none" - isCompact={false} - selectedDataListItemId="" - wrapModifier={null} -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-none" - /> -</DataList> -`; - -exports[`DataList DataList variants Breakpoint - sm 1`] = ` -<DataList - aria-label="this is a simple list" - className="" - gridBreakpoint="sm" - isCompact={false} - selectedDataListItemId="" - wrapModifier={null} -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-sm" - /> -</DataList> -`; - -exports[`DataList DataList variants Breakpoint - xl 1`] = ` -<DataList - aria-label="this is a simple list" - className="" - gridBreakpoint="xl" - isCompact={false} - selectedDataListItemId="" - wrapModifier={null} -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-xl" - /> -</DataList> -`; - -exports[`DataList DataListAction button 1`] = ` -<div - className="pf-c-data-list__item-action" -> - <Button - id="delete-item-1" - > - Delete - </Button> -</div> -`; - -exports[`DataList DataListAction dropdown 1`] = ` -<div - className="pf-c-data-list__item-action" -> - <div - className="pf-c-data-list__action" - > - <Dropdown - dropdownItems={ - Array [ - <DropdownItem - component="button" - onClick={[MockFunction]} - > - action-1 - </DropdownItem>, - <DropdownItem - component="button" - onClick={[MockFunction]} - > - action-2 - </DropdownItem>, - ] - } - isPlain={true} - position="right" - toggle={<KebabToggle />} - /> - </div> -</div> -`; - -exports[`DataList DataListContent 1`] = ` -<section - aria-label="Primary Content Details" - className="pf-c-data-list__expandable-content" - hidden={false} - id="" -> - <div - className="pf-c-data-list__expandable-content-body" - > - test - </div> -</section> -`; - -exports[`DataList DataListContent hasNoPadding 1`] = ` -<section - aria-label="Primary Content Details" - className="pf-c-data-list__expandable-content" - hidden={true} - id="" -> - <div - className="pf-c-data-list__expandable-content-body pf-m-no-padding" - > - test - </div> -</section> -`; - -exports[`DataList Item 1`] = ` -<ContextConsumer> - <Component /> -</ContextConsumer> -`; - -exports[`DataList Item default 1`] = ` -<ContextConsumer> - <Component /> -</ContextConsumer> -`; - -exports[`DataList List 1`] = ` -<ContextProvider - value={ - Object { - "dragEnd": [Function], - "dragKeyHandler": [Function], - "dragStart": [Function], - "drop": [Function], - "isDraggable": false, - "isSelectable": false, - "selectedDataListItemId": "", - "updateSelectedDataListItem": [Function], - } - } -> +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-md data-list-custom" + aria-label="list" + class="pf-v6-c-data-list pf-m-grid-md" + role="list" /> -</ContextProvider> -`; - -exports[`DataList List compact 1`] = ` -<ContextProvider - value={ - Object { - "dragEnd": [Function], - "dragKeyHandler": [Function], - "dragStart": [Function], - "drop": [Function], - "isDraggable": false, - "isSelectable": false, - "selectedDataListItemId": "", - "updateSelectedDataListItem": [Function], - } - } -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-compact pf-m-grid-md" - /> -</ContextProvider> -`; - -exports[`DataList List default 1`] = ` -<ContextProvider - value={ - Object { - "dragEnd": [Function], - "dragKeyHandler": [Function], - "dragStart": [Function], - "drop": [Function], - "isDraggable": false, - "isSelectable": false, - "selectedDataListItemId": "", - "updateSelectedDataListItem": [Function], - } - } -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-grid-md" - /> -</ContextProvider> -`; - -exports[`DataList List draggable 1`] = ` -<ContextProvider - value={ - Object { - "dragEnd": [Function], - "dragKeyHandler": [Function], - "dragStart": [Function], - "drop": [Function], - "isDraggable": true, - "isSelectable": false, - "selectedDataListItemId": "", - "updateSelectedDataListItem": [Function], - } - } -> - <ul - aria-label="this is a simple list" - className="pf-c-data-list pf-m-compact pf-m-grid-md" - onDragLeave={[Function]} - onDragOver={[Function]} - onDrop={[Function]} - /> -</ContextProvider> -`; - -exports[`DataList item row default 1`] = ` -<div - className="pf-c-data-list__item-row" -/> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListAction.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListAction.test.tsx.snap new file mode 100644 index 00000000000..483c34f6202 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListAction.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-data-list__item-action" + > + test + </div> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListCell.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListCell.test.tsx.snap new file mode 100644 index 00000000000..8f8739ce11b --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListCell.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Cell renders to match snapshot 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-data-list__cell" + > + Secondary + </div> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListContent.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListContent.test.tsx.snap new file mode 100644 index 00000000000..bf5b150f5ad --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListContent.test.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <section + aria-label="Primary Content Details" + class="pf-v6-c-data-list__expandable-content" + id="" + > + <div + class="pf-v6-c-data-list__expandable-content-body" + > + test + </div> + </section> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItem.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItem.test.tsx.snap new file mode 100644 index 00000000000..3ecc65cd56d --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItem.test.tsx.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <li + class="pf-v6-c-data-list__item" + id="" + /> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItemCells.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItemCells.test.tsx.snap new file mode 100644 index 00000000000..39da6b9ec38 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItemCells.test.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Cells renders to match snapshot 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-data-list__item-content" + /> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItemRow.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItemRow.test.tsx.snap new file mode 100644 index 00000000000..e7f65055770 --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListItemRow.test.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Item row renders to match snapshot 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-data-list__item-row" + /> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListToggle.test.tsx.snap b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListToggle.test.tsx.snap new file mode 100644 index 00000000000..3030121ed4f --- /dev/null +++ b/packages/react-core/src/components/DataList/__tests__/__snapshots__/DataListToggle.test.tsx.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-data-list__item-control" + > + <div + class="pf-v6-c-data-list__toggle" + > + <button + aria-controls="false" + aria-expanded="false" + aria-label="Details" + aria-labelledby=" ex-toggle2" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:r0:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + id="ex-toggle2" + type="button" + > + <span + class="pf-v6-c-button__icon" + > + <div + class="pf-v6-c-data-list__toggle-icon" + > + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" + > + <path + d="M18.71 5.29a.996.996 0 0 0-1.41 0l-7.29 7.29-7.3-7.29a.987.987 0 0 0-1.41-.02.987.987 0 0 0-.02 1.41l.02.02 7.65 7.65c.29.29.68.44 1.06.44s.77-.15 1.06-.44l7.65-7.65a.996.996 0 0 0 0-1.41Z" + /> + </svg> + </div> + </span> + </button> + </div> + </div> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DataList/examples/DataList.md b/packages/react-core/src/components/DataList/examples/DataList.md index b3436b2b9a0..57c61e9df9a 100644 --- a/packages/react-core/src/components/DataList/examples/DataList.md +++ b/packages/react-core/src/components/DataList/examples/DataList.md @@ -1,7 +1,7 @@ --- id: Data list section: components -cssPrefix: pf-c-data-list +cssPrefix: pf-v6-c-data-list propComponents: [ 'DataList', @@ -14,1250 +14,104 @@ propComponents: 'DataListToggle', 'DataListContent', 'DataListDragButton', - 'DataListControl', + 'DataListControl' ] --- +import { Fragment, useState } from 'react'; import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon'; -import AngleDownIcon from '@patternfly/react-icons/dist/esm/icons/angle-down-icon'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon'; +import RhMicronsCaretRightIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-right-icon'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; import { css } from '@patternfly/react-styles'; +import { DragDropSort, DragDropContainer, Droppable as NewDroppable } from '@patternfly/react-drag-drop'; ## Examples ### Basic -```js -import React from 'react'; -import { - Button, - DataList, - DataListItem, - DataListItemRow, - DataListItemCells, - DataListCell, - DataListCheck, - DataListAction, - DataListToggle, - DataListContent, - Dropdown, - KebabToggle, - DropdownItem -} from '@patternfly/react-core'; +```ts file="./DataListBasic.tsx" -<DataList aria-label="Simple data list example"> - <DataListItem aria-labelledby="simple-item1"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="simple-item1">Primary content</span> - </DataListCell>, - <DataListCell key="secondary content">Secondary content</DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> - <DataListItem aria-labelledby="simple-item2"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell isFilled={false} key="secondary content fill"> - <span id="simple-item2">Secondary content (pf-m-no-fill)</span> - </DataListCell>, - <DataListCell isFilled={false} alignRight key="secondary content align"> - Secondary content (pf-m-align-right pf-m-no-fill) - </DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> -</DataList> ``` ### Compact -```js -import React from 'react'; -import { - Button, - DataList, - DataListItem, - DataListItemRow, - DataListItemCells, - DataListCell, - DataListCheck, - DataListAction, - DataListToggle, - DataListContent, - Dropdown, - KebabToggle, - DropdownItem -} from '@patternfly/react-core'; +```ts file="./DataListCompact.tsx" -<DataList aria-label="Compact data list example" isCompact> - <DataListItem aria-labelledby="simple-item1"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="simple-item1">Primary content</span> - </DataListCell>, - <DataListCell key="secondary content">Secondary content</DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> - <DataListItem aria-labelledby="simple-item2"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell isFilled={false} key="secondary content fill"> - <span id="simple-item2">Secondary content (pf-m-no-fill)</span> - </DataListCell>, - <DataListCell isFilled={false} alignRight key="secondary content align"> - Secondary content (pf-m-align-right pf-m-no-fill) - </DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> -</DataList> ``` -### Checkboxes, actions and additional cells - -```js -import React from 'react'; -import { - Button, - DataList, - DataListActionModifiers, - DataListItem, - DataListItemCells, - DataListItemRow, - DataListCell, - DataListCheck, - DataListAction, - Dropdown, - DropdownItem, - DropdownPosition, - KebabToggle -} from '@patternfly/react-core'; - -class CheckboxActionDataList extends React.Component { - constructor(props) { - super(props); - this.state = { isOpen1: false, isOpen2: false, isOpen3: false }; - - this.onToggle1 = isOpen1 => { - this.setState({ isOpen1 }); - }; +### Plain - this.onSelect1 = event => { - this.setState(prevState => ({ - isOpen1: !prevState.isOpen1 - })); - }; +```ts file="./DataListPlain.tsx" - this.onToggle2 = isOpen2 => { - this.setState({ isOpen2 }); - }; - - this.onSelect2 = event => { - this.setState(prevState => ({ - isOpen2: !prevState.isOpen2 - })); - }; +``` - this.onToggle3 = isOpen3 => { - this.setState({ isOpen3 }); - }; +### Checkboxes, actions and additional cells - this.onSelect3 = event => { - this.setState(prevState => ({ - isOpen3: !prevState.isOpen3 - })); - }; - } +```ts file="./DataListCheckboxes.tsx" - render() { - return ( - <DataList aria-label="Checkbox and action data list example"> - <DataListItem aria-labelledby="check-action-item1"> - <DataListItemRow> - <DataListCheck aria-labelledby="check-action-item1" name="check-action-check1" /> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="check-action-item1">Primary content</span> Dolor sit amet, consectetur adipisicing elit, sed - do eiusmod. - </DataListCell>, - <DataListCell key="secondary content 1"> - Secondary content. Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. - </DataListCell>, - <DataListCell key="secondary content 2"> - <span>Tertiary content</span> Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. - </DataListCell>, - <DataListCell key="more content 1"> - <span>More content</span> Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. - </DataListCell>, - <DataListCell key="more content 2"> - <span>More content</span> Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. - </DataListCell> - ]} - /> - <DataListAction - aria-labelledby="check-action-item1 check-action-action1" - id="check-action-action1" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen1} - onSelect={this.onSelect1} - toggle={<KebabToggle onToggle={this.onToggle1} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - </DataListItem> - <DataListItem aria-labelledby="check-action-item2"> - <DataListItemRow> - <DataListCheck aria-labelledby="check-action-item2" name="check-action-check2" /> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="check-action-item2">Primary content - Lorem ipsum</span> dolor sit amet, consectetur - adipisicing elit, sed do eiusmod. - </DataListCell>, - <DataListCell key="secondary content"> - Secondary content. Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. - </DataListCell> - ]} - /> - <DataListAction - visibility={{ lg: 'hidden' }} - aria-labelledby="check-action-item2 check-action-action2" - id="check-action-action2" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen2} - onSelect={this.onSelect2} - toggle={<KebabToggle onToggle={this.onToggle2} />} - dropdownItems={[ - <DropdownItem key="pri-action2" component="button"> - Primary - </DropdownItem>, - <DropdownItem key="sec-action2" component="button"> - Secondary - </DropdownItem> - ]} - /> - </DataListAction> - <DataListAction - visibility={{ default: 'hidden', lg: 'visible' }} - aria-labelledby="check-action-item2 check-action-action2" - id="check-action-action2" - aria-label="Actions" - > - <Button variant="primary">Primary</Button> - <Button variant="secondary">Secondary</Button> - </DataListAction> - </DataListItemRow> - </DataListItem> - <DataListItem aria-labelledby="check-action-item3"> - <DataListItemRow> - <DataListCheck aria-labelledby="check-action-item3" name="check-action-check3" /> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="check-action-item3">Primary content - Lorem ipsum</span> dolor sit amet, consectetur - adipisicing elit, sed do eiusmod. - </DataListCell>, - <DataListCell key="secondary content"> - Secondary content. Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. - </DataListCell> - ]} - /> - <DataListAction - visibility={{ xl: 'hidden' }} - aria-labelledby="check-action-item3 check-action-action3" - id="check-action-action3" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen3} - onSelect={this.onSelect3} - toggle={<KebabToggle onToggle={this.onToggle3} />} - dropdownItems={[ - <DropdownItem key="pri-action3" component="button"> - Primary - </DropdownItem>, - <DropdownItem key="sec1-action3" component="button"> - Secondary - </DropdownItem>, - <DropdownItem key="sec2-action3" component="button"> - Secondary - </DropdownItem>, - <DropdownItem key="sec3-action3" component="button"> - Secondary - </DropdownItem> - ]} - /> - </DataListAction> - <DataListAction - visibility={{ default: 'hidden', xl: 'visible' }} - aria-labelledby="check-action-item3 check-action-action3" - id="check-action-action3" - aria-label="Actions" - > - <Button variant="primary">Primary</Button> - <Button variant="secondary">Secondary</Button> - <Button variant="secondary">Secondary</Button> - <Button variant="secondary">Secondary</Button> - </DataListAction> - </DataListItemRow> - </DataListItem> - </DataList> - ); - } -} ``` ### Actions: single and multiple -```js -import React from 'react'; -import { - Button, - Dropdown, - DropdownItem, - DropdownPosition, - KebabToggle, - DataList, - DataListItem, - DataListCell, - DataListItemRow, - DataListCheck, - DataListItemCells, - DataListAction -} from '@patternfly/react-core'; - -class ActionsDataList extends React.Component { - constructor(props) { - super(props); - this.state = { isOpen: false, isDeleted: false }; +```ts file="./DataListActions.tsx" - this.onToggle = isOpen => { - this.setState({ isOpen }); - }; - - this.onSelect = event => { - this.setState(prevState => ({ - isOpen: !prevState.isOpen - })); - }; - } - - render() { - return ( - <React.Fragment> - <DataList aria-label="single action data list example "> - {!this.state.isDeleted && ( - <DataListItem aria-labelledby="single-action-item1"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="single-action-item1">Single actionable Primary content</span> - </DataListCell>, - <DataListCell key="secondary content">Single actionable Secondary content</DataListCell> - ]} - /> - <DataListAction - aria-labelledby="single-action-item1 single-action-action1" - id="single-action-action1" - aria-label="Actions" - > - <Button - onClick={() => { - if (confirm('Are you sure?')) { - this.setState({ isDeleted: true }); - } - }} - variant="primary" - key="delete-action" - > - Delete - </Button> - </DataListAction> - </DataListItemRow> - </DataListItem> - )} - <DataListItem aria-labelledby="multi-actions-item1"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="multi-actions-item1">Multi actions Primary content</span> - </DataListCell>, - <DataListCell key="secondary content">Multi actions Secondary content</DataListCell> - ]} - /> - <DataListAction - aria-labelledby="multi-actions-item1 multi-actions-action1" - id="multi-actions-action1" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen} - onSelect={this.onSelect} - toggle={<KebabToggle onToggle={this.onToggle} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - </DataListItem> - </DataList> - </React.Fragment> - ); - } -} ``` ### Expandable -```js -import React from 'react'; -import { - Button, - DataList, - DataListItem, - DataListItemRow, - DataListCell, - DataListCheck, - DataListAction, - DataListToggle, - DataListContent, - DataListItemCells, - Dropdown, - DropdownItem, - DropdownPosition, - KebabToggle -} from '@patternfly/react-core'; -import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon'; -import AngleDownIcon from '@patternfly/react-icons/dist/esm/icons/angle-down-icon'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; - -class ExpandableDataList extends React.Component { - constructor(props) { - super(props); - this.state = { - expanded: ['ex-toggle1', 'ex-toggle3'], - isOpen1: false, - isOpen2: false, - isOpen3: false, - allExpanded: false - }; - - this.onToggleAll = () => { - this.setState( - { - allExpanded: !this.state.allExpanded - }, - () => { - if (this.state.allExpanded) { - this.setState({ - expanded: ['ex-toggle1', 'ex-toggle2', 'ex-toggle3'] - }); - } else { - this.setState({ - expanded: [] - }); - } - } - ); - }; - - this.onToggle1 = isOpen1 => { - this.setState({ isOpen1 }); - }; - - this.onToggle2 = isOpen2 => { - this.setState({ isOpen2 }); - }; +```ts file="./DataListExpandable.tsx" - this.onToggle3 = isOpen3 => { - this.setState({ isOpen3 }); - }; - - this.onSelect1 = event => { - this.setState(prevState => ({ - isOpen1: !prevState.isOpen1 - })); - }; +``` - this.onSelect2 = event => { - this.setState(prevState => ({ - isOpen2: !prevState.isOpen2 - })); - }; +### Mixed expandable - this.onSelect3 = event => { - this.setState(prevState => ({ - isOpen3: !prevState.isOpen3 - })); - }; - } +```ts file="./DataListMixedExpandable.tsx" - render() { - const toggle = id => { - const expanded = this.state.expanded; - const index = expanded.indexOf(id); - const newExpanded = - index >= 0 ? [...expanded.slice(0, index), ...expanded.slice(index + 1, expanded.length)] : [...expanded, id]; - this.setState(() => ({ expanded: newExpanded })); - }; - return ( - <React.Fragment> - <Button onClick={this.onToggleAll}> - {this.state.allExpanded && <AngleDownIcon />} - {!this.state.allExpanded && <AngleRightIcon />} - Expand/Collapse All - </Button> - <br /> - <br /> - <DataList aria-label="Expandable data list example"> - <DataListItem aria-labelledby="ex-item1" isExpanded={this.state.expanded.includes('ex-toggle1')}> - <DataListItemRow> - <DataListToggle - onClick={() => toggle('ex-toggle1')} - isExpanded={this.state.expanded.includes('ex-toggle1')} - id="ex-toggle1" - aria-controls="ex-expand1" - /> - <DataListItemCells - dataListCells={[ - <DataListCell isIcon key="icon"> - <CodeBranchIcon /> - </DataListCell>, - <DataListCell key="primary content"> - <div id="ex-item1">Primary content</div> - <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> - <a href="#">link</a> - </DataListCell>, - <DataListCell key="secondary content"> - <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> - </DataListCell>, - <DataListCell key="secondary content 2"> - <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> - </DataListCell> - ]} - /> - <DataListAction - aria-labelledby="ex-item1 ex-action1" - id="ex-action1" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen1} - onSelect={this.onSelect1} - toggle={<KebabToggle onToggle={this.onToggle1} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - <DataListContent - aria-label="Primary Content Details" - id="ex-expand1" - isHidden={!this.state.expanded.includes('ex-toggle1')} - > - <p> - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et - dolore magna aliqua. - </p> - </DataListContent> - </DataListItem> - <DataListItem aria-labelledby="ex-item2" isExpanded={this.state.expanded.includes('ex-toggle2')}> - <DataListItemRow> - <DataListToggle - onClick={() => toggle('ex-toggle2')} - isExpanded={this.state.expanded.includes('ex-toggle2')} - id="ex-toggle2" - aria-controls="ex-expand2" - /> - <DataListItemCells - dataListCells={[ - <DataListCell isIcon key="icon"> - <CodeBranchIcon /> - </DataListCell>, - <DataListCell key="secondary content"> - <div id="ex-item2">Secondary content</div> - <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> - </DataListCell>, - <DataListCell key="secondary content 2"> - <span>Lorem ipsum dolor sit amet.</span> - </DataListCell>, - <DataListCell key="secondary content3"> - <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> - </DataListCell> - ]} - /> - <DataListAction - aria-labelledby="ex-item2 ex-action2" - id="ex-action2" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen2} - onSelect={this.onSelect2} - toggle={<KebabToggle onToggle={this.onToggle2} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - <DataListContent - aria-label="Primary Content Details" - id="ex-expand2" - isHidden={!this.state.expanded.includes('ex-toggle2')} - > - <p> - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et - dolore magna aliqua. - </p> - </DataListContent> - </DataListItem> - <DataListItem aria-labelledby="ex-item3" isExpanded={this.state.expanded.includes('ex-toggle3')}> - <DataListItemRow> - <DataListToggle - onClick={() => toggle('ex-toggle3')} - isExpanded={this.state.expanded.includes('ex-toggle3')} - id="ex-toggle3" - aria-controls="ex-expand3" - /> - <DataListItemCells - dataListCells={[ - <DataListCell isIcon key="icon"> - <CodeBranchIcon /> - </DataListCell>, - <DataListCell key="tertiary content"> - <div id="ex-item3">Tertiary content</div> - <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> - </DataListCell>, - <DataListCell key="secondary content"> - <span>Lorem ipsum dolor sit amet.</span> - </DataListCell>, - <DataListCell key="secondary content 2"> - <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> - </DataListCell> - ]} - /> - <DataListAction - aria-labelledby="ex-item3 ex-action3" - aria-labelledby="ex-item3 ex-action3" - id="ex-action3" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen3} - onSelect={this.onSelect3} - toggle={<KebabToggle onToggle={this.onToggle3} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - <DataListContent - aria-label="Primary Content Details" - id="ex-expand3" - isHidden={!this.state.expanded.includes('ex-toggle3')} - hasNoPadding - > - This expanded section has no padding. - </DataListContent> - </DataListItem> - </DataList> - </React.Fragment> - ); - } -} ``` ### Width modifiers -```js -import React from 'react'; -import { - Button, - DataList, - DataListItem, - DataListCell, - DataListCheck, - DataListAction, - DataListToggle, - DataListContent, - DataListItemCells, - DataListItemRow, - Dropdown, - DropdownItem, - KebabToggle -} from '@patternfly/react-core'; - -class ModifiersDataList extends React.Component { - constructor(props) { - super(props); - this.state = { show: true, isOpen1: false, isOpen2: false, isOpen3: false }; - - this.onToggle1 = isOpen1 => { - this.setState({ isOpen1 }); - }; - - this.onToggle2 = isOpen2 => { - this.setState({ isOpen2 }); - }; - - this.onSelect1 = event => { - this.setState(prevState => ({ - isOpen1: !prevState.isOpen1 - })); - }; - - this.onSelect2 = event => { - this.setState(prevState => ({ - isOpen2: !prevState.isOpen2 - })); - }; - } - - render() { - const previewPlaceholder = { - display: 'block', - width: '100%', - padding: '.25rem .5rem', - color: '#004e8a', - backgroundColor: '#def3ff', - border: '1px solid rgba(0,0,0,.1)', - borderRadius: '4px' - }; +```ts file="./DataListWidthModifiers.tsx" - return [ - <div key="example-1"> - <h2>Default fitting - example 1</h2> - <DataList aria-label="Width modifier data list example 1"> - <DataListItem aria-labelledby="width-ex1-item1"> - <DataListItemRow> - <DataListCheck aria-labelledby="width-ex1-item1" name="width-ex1-item1" /> - <DataListItemCells - dataListCells={[ - <DataListCell key="default"> - <div style={previewPlaceholder}> - <b id="width-ex1-item1">default</b> - <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> - </div> - </DataListCell>, - <DataListCell key="default2"> - <div style={previewPlaceholder}> - <b>default</b> - <p> - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut - labore et dolore magna aliqua. - </p> - </div> - </DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> - </DataList> - </div>, - <div key="example-2"> - <h2>Flex modifiers - example 2</h2> - <DataList aria-label="Width modifier data list example 2"> - <DataListItem aria-labelledby="width-ex2-item1"> - <DataListItemRow> - <DataListCheck aria-labelledby="width-ex2-item1" name="width-ex2-item1" /> - <DataListItemCells - dataListCells={[ - <DataListCell width={2} key="width 2"> - <div style={previewPlaceholder}> - <b id="width-ex2-item1">width 2</b> - <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt.</p> - </div> - </DataListCell>, - <DataListCell width={4} key="width 4"> - <div style={previewPlaceholder}> - <b>width 4</b> - <p>Lorem ipsum dolor sit amet.</p> - </div> - </DataListCell> - ]} - /> - <DataListAction - aria-labelledby="width-ex2-item1 width-ex2-action1" - id="width-ex2-action1" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen1} - onSelect={this.onSelect1} - toggle={<KebabToggle onToggle={this.onToggle1} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - </DataListItem> - </DataList> - </div>, - <div key="example-3"> - <h2>Flex modifiers - example 3</h2> - <DataList aria-label="Width modifier data list example 3"> - <DataListItem aria-labelledby="width-ex3-item1" isExpanded={this.state.show}> - <DataListItemRow> - <DataListToggle - isExpanded={this.state.show} - id="width-ex3-toggle1" - aria-controls="width-ex3-expand1" - onClick={() => this.setState({ show: !this.state.show })} - /> - <DataListCheck aria-labelledby="width-ex3-item1" name="width-ex3-item1" /> - <DataListItemCells - dataListCells={[ - <DataListCell width={5} key="width 5"> - <div style={previewPlaceholder}> - <b id="width-ex3-item1">width 5</b> - <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> - </div> - </DataListCell>, - <DataListCell width={2} key="width 2"> - <div style={previewPlaceholder}> - <b>width 2</b> - <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> - </div> - </DataListCell>, - <DataListCell key="default"> - <div style={previewPlaceholder}>default</div> - </DataListCell> - ]} - /> - <DataListAction - aria-labelledby="width-ex3-item1 width-ex3-action1" - id="width-ex3-action1" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen2} - onSelect={this.onSelect2} - toggle={<KebabToggle onToggle={this.onToggle2} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - <DataListContent aria-label="Primary Content Details" id="width-ex3-expand1" isHidden={!this.state.show}> - <p> - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et - dolore magna aliqua. - </p> - </DataListContent> - </DataListItem> - </DataList> - </div> - ]; - } -} ``` -### Selectable rows +### Clickable rows -```js -import React from 'react'; -import { - Button, - Dropdown, - DropdownItem, - DropdownPosition, - KebabToggle, - DataList, - DataListItem, - DataListCell, - DataListItemRow, - DataListCheck, - DataListItemCells, - DataListAction -} from '@patternfly/react-core'; +```ts file="./DataListClickableRows.tsx" -class SelectableDataList extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen1: false, - isOpen2: false, - selectedDataListItemId: '' - }; - - this.onToggle1 = isOpen1 => { - this.setState({ isOpen1 }); - }; - - this.onToggle2 = isOpen2 => { - this.setState({ isOpen2 }); - }; - - this.onSelect1 = event => { - this.setState(prevState => ({ - isOpen1: !prevState.isOpen1 - })); - }; - - this.onSelect2 = event => { - this.setState(prevState => ({ - isOpen2: !prevState.isOpen2 - })); - }; - - this.onSelectDataListItem = id => { - this.setState({ selectedDataListItemId: id }); - }; - } - - render() { - return ( - <React.Fragment> - <DataList - aria-label="selectable data list example" - selectedDataListItemId={this.state.selectedDataListItemId} - onSelectDataListItem={this.onSelectDataListItem} - > - {!this.state.isDeleted && ( - <DataListItem aria-labelledby="selectable-action-item1" id="item1"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="selectable-action-item1">Single actionable Primary content</span> - </DataListCell>, - <DataListCell key="secondary content">Single actionable Secondary content</DataListCell> - ]} - /> - <DataListAction - aria-labelledby="selectable-action-item1 selectable-action-action1" - id="selectable-action-action1" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen1} - onSelect={this.onSelect1} - toggle={<KebabToggle onToggle={this.onToggle1} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - </DataListItem> - )} - <DataListItem aria-labelledby="selectable-actions-item2" id="item2"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="selectable-actions-item2">Selectable actions Primary content</span> - </DataListCell>, - <DataListCell key="secondary content">Selectable actions Secondary content</DataListCell> - ]} - /> - <DataListAction - aria-labelledby="selectable-actions-item2 selectable-actions-action2" - id="selectable-actions-action2" - aria-label="Actions" - isPlainButtonAction - > - <Dropdown - isPlain - position={DropdownPosition.right} - isOpen={this.state.isOpen2} - onSelect={this.onSelect2} - toggle={<KebabToggle onToggle={this.onToggle2} />} - dropdownItems={[ - <DropdownItem key="link">Link</DropdownItem>, - <DropdownItem key="action" component="button"> - Action - </DropdownItem>, - <DropdownItem key="disabled link" isDisabled> - Disabled Link - </DropdownItem> - ]} - /> - </DataListAction> - </DataListItemRow> - </DataListItem> - </DataList> - </React.Fragment> - ); - } -} ``` ### Controlling text -```js -import React from 'react'; -import { - Button, - DataList, - DataListItem, - DataListItemRow, - DataListItemCells, - DataListCell, - DataListCheck, - DataListAction, - DataListWrapModifier -} from '@patternfly/react-core'; +```ts file="./DataListControllingText.tsx" -<DataList aria-label="Simple data list example"> - <DataListItem aria-labelledby="simple-item1"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content" wrapModifier={DataListWrapModifier.breakWord}> - <span id="simple-item1">Primary content</span> - </DataListCell>, - <DataListCell key="secondary content" wrapModifier={DataListWrapModifier.truncate}> - Really really really really really really really really really really really really really really long - description that should be truncated before it ends - </DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> -</DataList> ``` ### Draggable -Draggable data lists used to have their own HTML5-based API for drag and drop, which wasn't able to fulfill requirements such as custom styling on items being dragged. So we wrote generic `DragDrop`, `Draggable`, and `Droppable` components for this purpose. Use those new components instead of the deprecated (and buggy!) HTML5-based API. +To enable drag and drop, wrap the `<DataList>` component with `<DragDropSort>`, define the `variant` property as "DataList", and pass both the sortable items and `onDrop` callback to `<DragDropSort>`. `<DragDropSort>` will create the component's usual children internally based on the items property, so children should not be passed to the wrapped component. -Note: Keyboard accessibility and screen reader accessibility for the `DragDrop` component are still in development. -```js isBeta -import React from 'react'; -import { - DataList, - DataListItem, - DataListCell, - DataListItemRow, - DataListCheck, - DataListControl, - DataListDragButton, - DataListItemCells, - DragDrop, - Draggable, - Droppable -} from '@patternfly/react-core'; +Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page. -const getItems = count => - Array.from({ length: count }, (v, k) => k).map(k => ({ - id: `item-${k}`, - content: `item ${k} `.repeat(k === 4 ? 20 : 1) - })); +```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DataListDraggable.tsx" -const reorder = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); - return result; -}; +``` -DraggableDataList = () => { - const [items, setItems] = React.useState(getItems(10)); - const [liveText, setLiveText] = React.useState(''); +### Draggable with multiple drop zones - function onDrag(source) { - setLiveText(`Started dragging ${items[source.index].content}`); - // Return true to allow drag - return true; - } +To enable multiple drop zones, and create the desired amount of `<Droppable>` components within a `<DragDropContainer>`. - function onDragMove(source, dest) { - const newText = dest - ? `Move ${items[source.index].content} to ${items[dest.index].content}` - : 'Invalid drop zone'; - if (newText !== liveText) { - setLiveText(newText); - } - } +Each `<Droppable>` should define the `wrapper` property as the component that acts as the drop zone, `<DataList>`, and the `items` property of their respective draggable items as an array of `<DraggableObject>` data. `<DragDropContainer>` should be passed the `onDrop`, `onContainerMove`, and `onCancel` callbacks to handle items being dropped, items moving between droppable containers, and what happens if the drag is cancelled respectively. `<DragDropContainer>` should also be given a `Record` representing all sortable drop zones' items. Both components should define the `variant` property as "DataList". - function onDrop(source, dest) { - if (dest) { - const newItems = reorder( - items, - source.index, - dest.index - ); - setItems(newItems); +Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page. - setLiveText('Dragging finished.'); - return true; // Signal that this is a valid drop and not to animate the item returning home. - } else { - setLiveText('Dragging cancelled. List unchanged.'); - } - } +```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DragDropContainerDataList.tsx" - return ( - <DragDrop onDrag={onDrag} onDragMove={onDragMove} onDrop={onDrop}> - <Droppable hasNoWrapper> - <DataList aria-label="draggable data list example" isCompact> - {items.map(({id, content}) => - <Draggable key={id} hasNoWrapper> - <DataListItem aria-labelledby={id} ref={React.createRef()}> - <DataListItemRow> - <DataListControl> - <DataListDragButton - aria-label="Reorder" - aria-labelledby={id} - aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation." - aria-pressed="false" - /> - <DataListCheck aria-labelledby={id} name={id} otherControls /> - </DataListControl> - <DataListItemCells - dataListCells={[ - <DataListCell key={id}> - <span id={id}>{content}</span> - </DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> - </Draggable> - )} - </DataList> - </Droppable> - <div className="pf-screen-reader" aria-live="assertive"> - {liveText} - </div> - </DragDrop> - ); -}; ``` ### Small grid breakpoint -```js -import React from 'react'; -import { - DataList, - DataListItem, - DataListItemRow, - DataListItemCells, - DataListCell -} from '@patternfly/react-core'; +```ts file="./DataListSmGridBreakpoint.tsx" -<DataList aria-label="Simple data list example" gridBreakpoint="sm"> - <DataListItem aria-labelledby="simple-item1"> - <DataListItemRow> - <DataListItemCells - dataListCells={[ - <DataListCell key="primary content"> - <span id="simple-item1">Primary content</span> - </DataListCell>, - <DataListCell key="secondary content"> - Really really really really really really really really really really really really really really long - description that should be truncated before it ends - </DataListCell> - ]} - /> - </DataListItemRow> - </DataListItem> -</DataList> ``` diff --git a/packages/react-core/src/components/DataList/examples/DataListActions.tsx b/packages/react-core/src/components/DataList/examples/DataListActions.tsx new file mode 100644 index 00000000000..fe828173a4b --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListActions.tsx @@ -0,0 +1,116 @@ +import { Fragment, useState } from 'react'; +import { + Button, + DataList, + DataListItem, + DataListCell, + DataListItemRow, + DataListItemCells, + DataListAction, + Dropdown, + DropdownList, + DropdownItem, + MenuToggle, + MenuToggleElement +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +export const DataListActions: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = useState(false); + const [isDeleted, setIsDeleted] = useState(false); + + const onToggle = () => { + setIsOpen(!isOpen); + }; + + const onSelect = () => { + setIsOpen(!isOpen); + }; + + return ( + <Fragment> + <DataList aria-label="single action data list example "> + {!isDeleted && ( + <DataListItem aria-labelledby="single-action-item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="single-action-item1">Single actionable Primary content</span> + </DataListCell>, + <DataListCell key="secondary content">Single actionable Secondary content</DataListCell> + ]} + /> + <DataListAction + aria-labelledby="single-action-item1 single-action-action1" + id="single-action-action1" + aria-label="Actions" + > + <Button + onClick={() => { + if (confirm('Are you sure?')) { + setIsDeleted(true); + } + }} + variant="primary" + key="delete-action" + > + Delete + </Button> + </DataListAction> + </DataListItemRow> + </DataListItem> + )} + <DataListItem aria-labelledby="multi-actions-item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="multi-actions-item1">Multi actions Primary content</span> + </DataListCell>, + <DataListCell key="secondary content">Multi actions Secondary content</DataListCell> + ]} + /> + <DataListAction + aria-labelledby="multi-actions-item1 multi-actions-action1" + id="multi-actions-action1" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen} + onClick={onToggle} + variant="plain" + aria-label="Data list with actions example kebab toggle" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen} + onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)} + > + <DropdownList> + <DropdownItem key="action">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + </DataListItem> + </DataList> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/DataList/examples/DataListBasic.tsx b/packages/react-core/src/components/DataList/examples/DataListBasic.tsx new file mode 100644 index 00000000000..e4af45501e9 --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListBasic.tsx @@ -0,0 +1,32 @@ +import { DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCell } from '@patternfly/react-core'; + +export const DataListBasic: React.FunctionComponent = () => ( + <DataList aria-label="Simple data list example"> + <DataListItem aria-labelledby="simple-item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="simple-item1">Primary content</span> + </DataListCell>, + <DataListCell key="secondary content">Secondary content</DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + <DataListItem aria-labelledby="simple-item2"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell isFilled={false} key="secondary content fill"> + <span id="simple-item2">Secondary content (pf-m-no-fill)</span> + </DataListCell>, + <DataListCell isFilled={false} alignRight key="secondary content align"> + Secondary content (pf-m-align-right pf-m-no-fill) + </DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + </DataList> +); diff --git a/packages/react-core/src/components/DataList/examples/DataListCheckboxes.tsx b/packages/react-core/src/components/DataList/examples/DataListCheckboxes.tsx new file mode 100644 index 00000000000..5138ce37093 --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListCheckboxes.tsx @@ -0,0 +1,241 @@ +import { useState } from 'react'; +import { + Button, + DataList, + DataListItem, + DataListItemCells, + DataListItemRow, + DataListCell, + DataListCheck, + DataListAction, + Dropdown, + DropdownList, + DropdownItem, + MenuToggle, + MenuToggleElement +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +export const DataListCheckboxes: React.FunctionComponent = () => { + const [isOpen1, setIsOpen1] = useState(false); + const [isOpen2, setIsOpen2] = useState(false); + const [isOpen3, setIsOpen3] = useState(false); + + const onToggle1 = () => { + setIsOpen1(!isOpen1); + }; + + const onSelect1 = () => { + setIsOpen1(!isOpen1); + }; + + const onToggle2 = () => { + setIsOpen2(!isOpen2); + }; + + const onSelect2 = () => { + setIsOpen2(!isOpen2); + }; + const onToggle3 = () => { + setIsOpen3(!isOpen3); + }; + + const onSelect3 = () => { + setIsOpen3(!isOpen3); + }; + + return ( + <DataList aria-label="Checkbox and action data list example"> + <DataListItem aria-labelledby="check-action-item1"> + <DataListItemRow> + <DataListCheck id="check-item1" aria-labelledby="check-action-item1" name="check-action-check1" /> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="check-action-item1">Primary content</span> Dolor sit amet, consectetur adipisicing elit, sed + do eiusmod. + </DataListCell>, + <DataListCell key="secondary content 1"> + Secondary content. Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. + </DataListCell>, + <DataListCell key="secondary content 2"> + <span>Tertiary content</span> Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. + </DataListCell>, + <DataListCell key="more content 1"> + <span>More content</span> Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. + </DataListCell>, + <DataListCell key="more content 2"> + <span>More content</span> Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. + </DataListCell> + ]} + /> + <DataListAction + aria-labelledby="check-action-item1 check-action-action1" + id="check-action-action1" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect1} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen1} + onClick={onToggle1} + variant="plain" + aria-label="Data list with checkboxes, actions and additional cells example kebab toggle 1" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen1} + onOpenChange={(isOpen: boolean) => setIsOpen1(isOpen)} + > + <DropdownList> + <DropdownItem key="action">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + </DataListItem> + <DataListItem aria-labelledby="check-action-item2"> + <DataListItemRow> + <DataListCheck id="check-item2" aria-labelledby="check-action-item2" name="check-action-check2" /> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="check-action-item2">Primary content - Lorem ipsum</span> dolor sit amet, consectetur + adipisicing elit, sed do eiusmod. + </DataListCell>, + <DataListCell key="secondary content"> + Secondary content. Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. + </DataListCell> + ]} + /> + <DataListAction + visibility={{ lg: 'hidden' }} + aria-labelledby="check-action-item2 check-action-action2" + id="check-action-action2" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect2} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen2} + onClick={onToggle2} + variant="plain" + aria-label="Data list with checkboxes, actions and additional cells example kebab toggle 2" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen2} + onOpenChange={(isOpen: boolean) => setIsOpen2(isOpen)} + > + <DropdownList> + <DropdownItem key="action2">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link2" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action2" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link2" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + <DataListAction + visibility={{ default: 'hidden', lg: 'visible' }} + aria-labelledby="check-action-item2 check-action-action2a" + id="check-action-action2a" + aria-label="Actions" + > + <Button variant="primary">Primary</Button> + <Button variant="secondary">Secondary</Button> + </DataListAction> + </DataListItemRow> + </DataListItem> + <DataListItem aria-labelledby="check-action-item3"> + <DataListItemRow> + <DataListCheck id="check-item3" aria-labelledby="check-action-item3" name="check-action-check3" /> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="check-action-item3">Primary content - Lorem ipsum</span> dolor sit amet, consectetur + adipisicing elit, sed do eiusmod. + </DataListCell>, + <DataListCell key="secondary content"> + Secondary content. Dolor sit amet, consectetur adipisicing elit, sed do eiusmod. + </DataListCell> + ]} + /> + <DataListAction + visibility={{ xl: 'hidden' }} + aria-labelledby="check-action-item3 check-action-action3" + id="check-action-action3" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect3} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen3} + onClick={onToggle3} + variant="plain" + aria-label="Data list with checkboxes, actions and additional cells example kebab toggle 3" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen3} + onOpenChange={(isOpen: boolean) => setIsOpen3(isOpen)} + > + <DropdownList> + <DropdownItem key="action3">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link3" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action3" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link3" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + <DataListAction + visibility={{ default: 'hidden', xl: 'visible' }} + aria-labelledby="check-action-item3 check-action-action3a" + id="check-action-action3a" + aria-label="Actions" + > + <Button variant="primary">Primary</Button> + <Button variant="secondary">Secondary</Button> + <Button variant="secondary">Secondary</Button> + <Button variant="secondary">Secondary</Button> + </DataListAction> + </DataListItemRow> + </DataListItem> + </DataList> + ); +}; diff --git a/packages/react-core/src/components/DataList/examples/DataListClickableRows.tsx b/packages/react-core/src/components/DataList/examples/DataListClickableRows.tsx new file mode 100644 index 00000000000..a23bd1ad94f --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListClickableRows.tsx @@ -0,0 +1,155 @@ +import { Fragment, useState } from 'react'; +import { + DataList, + DataListItem, + DataListCell, + DataListItemRow, + DataListItemCells, + DataListAction, + Dropdown, + DropdownList, + DropdownItem, + MenuToggle, + MenuToggleElement +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +export const DataListClickableRows: React.FunctionComponent = () => { + const [isOpen1, setIsOpen1] = useState(false); + const [isOpen2, setIsOpen2] = useState(false); + const [selectedDataListItemId, setSelectedDataListItemId] = useState(''); + + const onToggle1 = () => { + setIsOpen1(!isOpen1); + }; + + const onSelect1 = () => { + setIsOpen1(!isOpen1); + }; + + const onToggle2 = () => { + setIsOpen2(!isOpen2); + }; + + const onSelect2 = () => { + setIsOpen2(!isOpen2); + }; + + const onSelectDataListItem = (_event: React.MouseEvent | React.KeyboardEvent, id: string) => { + setSelectedDataListItemId(id); + }; + + const handleInputChange = (_event: React.FormEvent<HTMLInputElement>, id: string) => { + setSelectedDataListItemId(id); + }; + + return ( + <Fragment> + <DataList + aria-label="clickable data list example" + selectedDataListItemId={selectedDataListItemId} + onSelectDataListItem={onSelectDataListItem} + onSelectableRowChange={handleInputChange} + > + <DataListItem aria-labelledby="clickable-action-item1" id="item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="clickable-action-item1">Single actionable Primary content</span> + </DataListCell>, + <DataListCell key="secondary content">Single actionable Secondary content</DataListCell> + ]} + /> + <DataListAction + aria-labelledby="clickable-action-item1 clickable-action-action1" + id="clickable-action-action1" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect1} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen1} + onClick={onToggle1} + variant="plain" + aria-label="Data list clickable rows example kebab toggle 1" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen1} + onOpenChange={(isOpen: boolean) => setIsOpen1(isOpen)} + > + <DropdownList> + <DropdownItem key="action">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + </DataListItem> + <DataListItem aria-labelledby="clickable-actions-item2" id="item2"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="clickable-actions-item2">clickable actions Primary content</span> + </DataListCell>, + <DataListCell key="secondary content">clickable actions Secondary content</DataListCell> + ]} + /> + <DataListAction + aria-labelledby="clickable-actions-item2 clickable-actions-action2" + id="clickable-actions-action2" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect2} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen2} + onClick={onToggle2} + variant="plain" + aria-label="Data list clickable rows example kebab toggle 2" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen2} + onOpenChange={(isOpen: boolean) => setIsOpen2(isOpen)} + > + <DropdownList> + <DropdownItem key="action2">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link2" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action2" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link2" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + </DataListItem> + </DataList> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/DataList/examples/DataListCompact.tsx b/packages/react-core/src/components/DataList/examples/DataListCompact.tsx new file mode 100644 index 00000000000..23644d59371 --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListCompact.tsx @@ -0,0 +1,32 @@ +import { DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCell } from '@patternfly/react-core'; + +export const DataListCompact: React.FunctionComponent = () => ( + <DataList aria-label="Compact data list example" isCompact> + <DataListItem aria-labelledby="compact-item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="compact-item1">Primary content</span> + </DataListCell>, + <DataListCell key="secondary content">Secondary content</DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + <DataListItem aria-labelledby="compact-item2"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell isFilled={false} key="secondary content fill"> + <span id="compact-item2">Secondary content (pf-m-no-fill)</span> + </DataListCell>, + <DataListCell isFilled={false} alignRight key="secondary content align"> + Secondary content (pf-m-align-right pf-m-no-fill) + </DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + </DataList> +); diff --git a/packages/react-core/src/components/DataList/examples/DataListControllingText.tsx b/packages/react-core/src/components/DataList/examples/DataListControllingText.tsx new file mode 100644 index 00000000000..01d5adc3b73 --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListControllingText.tsx @@ -0,0 +1,28 @@ +import { + DataList, + DataListItem, + DataListItemRow, + DataListItemCells, + DataListCell, + DataListWrapModifier +} from '@patternfly/react-core'; + +export const DataListControllingText: React.FunctionComponent = () => ( + <DataList aria-label="Controlling text data list example"> + <DataListItem aria-labelledby="controlling-text-item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content" wrapModifier={DataListWrapModifier.breakWord}> + <span id="controlling-text-item1">Primary content</span> + </DataListCell>, + <DataListCell key="secondary content" wrapModifier={DataListWrapModifier.truncate}> + Really really really really really really really really really really really really really really long + description that should be truncated before it ends + </DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + </DataList> +); diff --git a/packages/react-core/src/components/DataList/examples/DataListExpandable.tsx b/packages/react-core/src/components/DataList/examples/DataListExpandable.tsx new file mode 100644 index 00000000000..7b94d233115 --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListExpandable.tsx @@ -0,0 +1,270 @@ +import { Fragment, useState } from 'react'; +import { + DataList, + DataListItem, + DataListItemRow, + DataListCell, + DataListAction, + DataListToggle, + DataListContent, + DataListItemCells, + Dropdown, + DropdownList, + DropdownItem, + MenuToggle, + MenuToggleElement +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; +import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon'; + +export const DataListExpandable: React.FunctionComponent = () => { + const [isOpen1, setIsOpen1] = useState(false); + const [isOpen2, setIsOpen2] = useState(false); + const [isOpen3, setIsOpen3] = useState(false); + const [expanded, setExpanded] = useState(['ex-toggle1', 'ex-toggle3']); + + const onToggle1 = () => { + setIsOpen1(!isOpen1); + }; + + const onSelect1 = () => { + setIsOpen1(!isOpen1); + }; + + const onToggle2 = () => { + setIsOpen2(!isOpen2); + }; + + const onSelect2 = () => { + setIsOpen2(!isOpen2); + }; + const onToggle3 = () => { + setIsOpen3(!isOpen3); + }; + + const onSelect3 = () => { + setIsOpen3(!isOpen3); + }; + + const toggle = (id) => { + const index = expanded.indexOf(id); + const newExpanded = + index >= 0 ? [...expanded.slice(0, index), ...expanded.slice(index + 1, expanded.length)] : [...expanded, id]; + setExpanded(newExpanded); + }; + return ( + <Fragment> + <DataList aria-label="Expandable data list example"> + <DataListItem aria-labelledby="ex-item1" isExpanded={expanded.includes('ex-toggle1')}> + <DataListItemRow> + <DataListToggle + onClick={() => toggle('ex-toggle1')} + isExpanded={expanded.includes('ex-toggle1')} + id="ex-toggle1" + aria-controls="ex-expand1" + /> + <DataListItemCells + dataListCells={[ + <DataListCell isIcon key="icon"> + <CodeBranchIcon /> + </DataListCell>, + <DataListCell key="primary content"> + <div id="ex-item1">Primary content</div> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + <a href="#">link</a> + </DataListCell>, + <DataListCell key="secondary content"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell>, + <DataListCell key="secondary content 2"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell> + ]} + /> + <DataListAction aria-labelledby="ex-item1 ex-action1" id="ex-action1" aria-label="Actions"> + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect1} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen1} + onClick={onToggle1} + variant="plain" + aria-label="Data list exapndable example kebaby toggle 1" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen1} + onOpenChange={(isOpen: boolean) => setIsOpen1(isOpen)} + > + <DropdownList> + <DropdownItem key="action">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + <DataListContent + aria-label="First expandable content details" + id="ex-expand1" + isHidden={!expanded.includes('ex-toggle1')} + > + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. + </p> + </DataListContent> + </DataListItem> + <DataListItem aria-labelledby="ex-item2" isExpanded={expanded.includes('ex-toggle2')}> + <DataListItemRow> + <DataListToggle + onClick={() => toggle('ex-toggle2')} + isExpanded={expanded.includes('ex-toggle2')} + id="ex-toggle2" + aria-controls="ex-expand2" + /> + <DataListItemCells + dataListCells={[ + <DataListCell isIcon key="icon"> + <CodeBranchIcon /> + </DataListCell>, + <DataListCell key="secondary content"> + <div id="ex-item2">Secondary content</div> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell>, + <DataListCell key="secondary content 2"> + <span>Lorem ipsum dolor sit amet.</span> + </DataListCell>, + <DataListCell key="secondary content3"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell> + ]} + /> + <DataListAction aria-labelledby="ex-item2 ex-action2" id="ex-action2" aria-label="Actions"> + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect2} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen2} + onClick={onToggle2} + variant="plain" + aria-label="Data list exapndable example kebaby toggle 2" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen2} + onOpenChange={(isOpen: boolean) => setIsOpen2(isOpen)} + > + <DropdownList> + <DropdownItem key="action2">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link2" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action2" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link2" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + <DataListContent + aria-label="Second expandable content details" + id="ex-expand2" + isHidden={!expanded.includes('ex-toggle2')} + > + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. + </p> + </DataListContent> + </DataListItem> + <DataListItem aria-labelledby="ex-item3" isExpanded={expanded.includes('ex-toggle3')}> + <DataListItemRow> + <DataListToggle + onClick={() => toggle('ex-toggle3')} + isExpanded={expanded.includes('ex-toggle3')} + id="ex-toggle3" + aria-controls="ex-expand3" + /> + <DataListItemCells + dataListCells={[ + <DataListCell isIcon key="icon"> + <CodeBranchIcon /> + </DataListCell>, + <DataListCell key="tertiary content"> + <div id="ex-item3">Tertiary content</div> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell>, + <DataListCell key="secondary content"> + <span>Lorem ipsum dolor sit amet.</span> + </DataListCell>, + <DataListCell key="secondary content 2"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell> + ]} + /> + <DataListAction aria-labelledby="ex-item3 ex-action3" id="ex-action3" aria-label="Actions"> + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect3} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen3} + onClick={onToggle3} + variant="plain" + aria-label="Data list exapndable example kebaby toggle 3" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen3} + onOpenChange={(isOpen: boolean) => setIsOpen3(isOpen)} + > + <DropdownList> + <DropdownItem key="action3">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link3" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action3" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link3" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + <DataListContent + aria-label="Third expandable content details" + id="ex-expand3" + isHidden={!expanded.includes('ex-toggle3')} + hasNoPadding + > + This expanded section has no padding. + </DataListContent> + </DataListItem> + </DataList> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/DataList/examples/DataListMixedExpandable.tsx b/packages/react-core/src/components/DataList/examples/DataListMixedExpandable.tsx new file mode 100644 index 00000000000..fd6eac75bfa --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListMixedExpandable.tsx @@ -0,0 +1,266 @@ +import { Fragment, useState } from 'react'; +import { + DataList, + DataListItem, + DataListItemRow, + DataListCell, + DataListAction, + DataListToggle, + DataListContent, + DataListItemCells, + Dropdown, + DropdownList, + DropdownItem, + MenuToggle, + MenuToggleElement +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; +import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon'; + +export const DataListMixedExpandable: React.FunctionComponent = () => { + const [isOpen1, setIsOpen1] = useState(false); + const [isOpen2, setIsOpen2] = useState(false); + const [isOpen3, setIsOpen3] = useState(false); + const [expanded, setExpanded] = useState(['m-ex-toggle1', 'm-ex-toggle3']); + + const onToggle1 = () => { + setIsOpen1(!isOpen1); + }; + + const onSelect1 = () => { + setIsOpen1(!isOpen1); + }; + + const onToggle2 = () => { + setIsOpen2(!isOpen2); + }; + + const onSelect2 = () => { + setIsOpen2(!isOpen2); + }; + + const onToggle3 = () => { + setIsOpen3(!isOpen3); + }; + + const onSelect3 = () => { + setIsOpen3(!isOpen3); + }; + + const toggle = (id) => { + const index = expanded.indexOf(id); + const newExpanded = + index >= 0 ? [...expanded.slice(0, index), ...expanded.slice(index + 1, expanded.length)] : [...expanded, id]; + setExpanded(newExpanded); + }; + + return ( + <Fragment> + <DataList aria-label="Mixed expandable data list example"> + <DataListItem aria-labelledby="m-ex-item1" isExpanded={expanded.includes('m-ex-toggle1')}> + <DataListItemRow> + <DataListToggle + onClick={() => toggle('m-ex-toggle1')} + isExpanded={expanded.includes('m-ex-toggle1')} + id="m-ex-toggle1" + aria-controls="m-ex-expand1" + /> + <DataListItemCells + dataListCells={[ + <DataListCell isIcon key="icon"> + <CodeBranchIcon /> + </DataListCell>, + <DataListCell key="primary content"> + <div id="m-ex-item1">Primary content</div> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + <a href="#">link</a> + </DataListCell>, + <DataListCell key="secondary content"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell>, + <DataListCell key="secondary content 2"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell> + ]} + /> + <DataListAction aria-labelledby="m-ex-item1 m-ex-action1" id="m-ex-action1" aria-label="Actions"> + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect1} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen1} + onClick={onToggle1} + variant="plain" + aria-label="Data list mixed expandable example kebab toggle 1" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen1} + onOpenChange={(isOpen: boolean) => setIsOpen1(isOpen)} + > + <DropdownList> + <DropdownItem key="action">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + <DataListContent + aria-label="First mixed expandable content details" + id="m-ex-expand1" + isHidden={!expanded.includes('m-ex-toggle1')} + > + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. + </p> + </DataListContent> + </DataListItem> + <DataListItem aria-labelledby="m-ex-item2"> + <DataListItemRow> + <DataListToggle + id="m-ex-toggle2" + buttonProps={{ + disabled: true, + 'aria-hidden': 'true', + style: { visibility: 'hidden' } + }} + /> + <DataListItemCells + dataListCells={[ + <DataListCell isIcon key="icon"> + <CodeBranchIcon /> + </DataListCell>, + <DataListCell key="secondary content"> + <div id="m-ex-item2">Secondary content</div> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell>, + <DataListCell key="secondary content 2"> + <span>Lorem ipsum dolor sit amet.</span> + </DataListCell>, + <DataListCell key="secondary content3"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell> + ]} + /> + <DataListAction aria-labelledby="m-ex-item2 m-ex-action2" id="m-ex-action2" aria-label="Actions"> + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect2} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen2} + onClick={onToggle2} + variant="plain" + aria-label="Data list mixed expandable example kebab toggle 2" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen2} + onOpenChange={(isOpen: boolean) => setIsOpen2(isOpen)} + > + <DropdownList> + <DropdownItem key="action2">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link2" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action2" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link2" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + </DataListItem> + <DataListItem aria-labelledby="m-ex-item3" isExpanded={expanded.includes('m-ex-toggle3')}> + <DataListItemRow> + <DataListToggle + onClick={() => toggle('m-ex-toggle3')} + isExpanded={expanded.includes('m-ex-toggle3')} + id="m-ex-toggle3" + aria-controls="m-ex-expand3" + /> + <DataListItemCells + dataListCells={[ + <DataListCell isIcon key="icon"> + <CodeBranchIcon /> + </DataListCell>, + <DataListCell key="tertiary content"> + <div id="m-ex-item3">Tertiary content</div> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell>, + <DataListCell key="secondary content"> + <span>Lorem ipsum dolor sit amet.</span> + </DataListCell>, + <DataListCell key="secondary content 2"> + <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> + </DataListCell> + ]} + /> + <DataListAction aria-labelledby="m-ex-item3 m-ex-action3" id="m-ex-action3" aria-label="Actions"> + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect3} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen3} + onClick={onToggle3} + variant="plain" + aria-label="Data list mixed expandable example kebab toggle 3" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen3} + onOpenChange={(isOpen: boolean) => setIsOpen3(isOpen)} + > + <DropdownList> + <DropdownItem key="action3">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link3" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action3" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem key="disabled link3" isDisabled to="#" onClick={(event: any) => event.preventDefault()}> + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + <DataListContent + aria-label="Third mixed expandable content details" + id="m-ex-expand3" + isHidden={!expanded.includes('m-ex-toggle3')} + > + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. + </p> + </DataListContent> + </DataListItem> + </DataList> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/DataList/examples/DataListPlain.tsx b/packages/react-core/src/components/DataList/examples/DataListPlain.tsx new file mode 100644 index 00000000000..af0b9f9618d --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListPlain.tsx @@ -0,0 +1,32 @@ +import { DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCell } from '@patternfly/react-core'; + +export const DataListPlain: React.FunctionComponent = () => ( + <DataList aria-label="Plain data list example" isPlain> + <DataListItem aria-labelledby="plain-item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="plain-item1">Primary content</span> + </DataListCell>, + <DataListCell key="secondary content">Secondary content</DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + <DataListItem aria-labelledby="plain-item2"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell isFilled={false} key="secondary content fill"> + <span id="plain-item2">Secondary content (pf-m-no-fill)</span> + </DataListCell>, + <DataListCell isFilled={false} alignRight key="secondary content align"> + Secondary content (pf-m-align-right pf-m-no-fill) + </DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + </DataList> +); diff --git a/packages/react-core/src/components/DataList/examples/DataListSmGridBreakpoint.tsx b/packages/react-core/src/components/DataList/examples/DataListSmGridBreakpoint.tsx new file mode 100644 index 00000000000..9beb45d5788 --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListSmGridBreakpoint.tsx @@ -0,0 +1,21 @@ +import { DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCell } from '@patternfly/react-core'; + +export const DataListSmGridBreakpoint: React.FunctionComponent = () => ( + <DataList aria-label="Small grid breakpoint list example" gridBreakpoint="sm"> + <DataListItem aria-labelledby="sm-grid-item1"> + <DataListItemRow> + <DataListItemCells + dataListCells={[ + <DataListCell key="primary content"> + <span id="sm-grid-item1">Primary content</span> + </DataListCell>, + <DataListCell key="secondary content"> + Really really really really really really really really really really really really really really long + description that should be truncated before it ends + </DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + </DataList> +); diff --git a/packages/react-core/src/components/DataList/examples/DataListWidthModifiers.tsx b/packages/react-core/src/components/DataList/examples/DataListWidthModifiers.tsx new file mode 100644 index 00000000000..f7cde4ca06d --- /dev/null +++ b/packages/react-core/src/components/DataList/examples/DataListWidthModifiers.tsx @@ -0,0 +1,218 @@ +import { useState } from 'react'; +import { + Content, + DataList, + DataListItem, + DataListCell, + DataListCheck, + DataListAction, + DataListToggle, + DataListContent, + DataListItemCells, + DataListItemRow, + Dropdown, + DropdownList, + DropdownItem, + MenuToggle, + MenuToggleElement +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +export const DataListWidthModifiers: React.FunctionComponent = () => { + const [show, setShow] = useState(true); + const [isOpen1, setIsOpen1] = useState(false); + const [isOpen2, setIsOpen2] = useState(false); + + const onToggle1 = () => { + setIsOpen1(!isOpen1); + }; + + const onSelect1 = () => { + setIsOpen1(!isOpen1); + }; + + const onToggle2 = () => { + setIsOpen2(!isOpen2); + }; + + const onSelect2 = () => { + setIsOpen2(!isOpen2); + }; + + return ( + <> + <div key="example-1"> + <Content> + <h4>Default fitting - example 1</h4> + </Content> + <DataList aria-label="Width modifier data list example 1"> + <DataListItem aria-labelledby="width-ex1-item1"> + <DataListItemRow> + <DataListCheck id="check-width-ex1-item1" aria-labelledby="width-ex1-item1" name="width-ex1-item1" /> + <DataListItemCells + dataListCells={[ + <DataListCell key="default"> + <b id="width-ex1-item1">default</b> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </DataListCell>, + <DataListCell key="default2"> + <b>default</b> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. + </p> + </DataListCell> + ]} + /> + </DataListItemRow> + </DataListItem> + </DataList> + </div> + <div key="example-2"> + <Content> + <h4>Flex modifiers - example 2</h4> + </Content> + <DataList aria-label="Width modifier data list example 2"> + <DataListItem aria-labelledby="width-ex2-item1"> + <DataListItemRow> + <DataListCheck id="check-width-ex2-item1" aria-labelledby="width-ex2-item1" name="width-ex2-item1" /> + <DataListItemCells + dataListCells={[ + <DataListCell width={2} key="width 2"> + <b id="width-ex2-item1">width 2</b> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt.</p> + </DataListCell>, + <DataListCell width={4} key="width 4"> + <b>width 4</b> + <p>Lorem ipsum dolor sit amet.</p> + </DataListCell> + ]} + /> + <DataListAction + aria-labelledby="width-ex2-item1 width-ex2-action1" + id="width-ex2-action1" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect1} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen1} + onClick={onToggle1} + variant="plain" + aria-label="Data list width modifiers example kebab toggle 1" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen1} + onOpenChange={(isOpen: boolean) => setIsOpen1(isOpen)} + > + <DropdownList> + <DropdownItem key="action">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem + key="disabled link" + isDisabled + to="#" + onClick={(event: any) => event.preventDefault()} + > + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + </DataListItem> + </DataList> + </div> + <div key="example-3"> + <Content> + <h4>Flex modifiers - example 3</h4> + </Content> + <DataList aria-label="Width modifier data list example 3"> + <DataListItem aria-labelledby="width-ex3-item1" isExpanded={show}> + <DataListItemRow> + <DataListToggle + isExpanded={show} + id="width-ex3-toggle1" + aria-controls="width-ex3-expand1" + onClick={() => setShow(!show)} + /> + <DataListCheck id="check-width-ex3-item1" aria-labelledby="width-ex3-item1" name="width-ex3-item1" /> + <DataListItemCells + dataListCells={[ + <DataListCell width={5} key="width 5"> + <b id="width-ex3-item1">width 5</b> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </DataListCell>, + <DataListCell width={2} key="width 2"> + <b>width 2</b> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </DataListCell>, + <DataListCell key="default">default</DataListCell> + ]} + /> + <DataListAction + aria-labelledby="width-ex3-item1 width-ex3-action1" + id="width-ex3-action1" + aria-label="Actions" + > + <Dropdown + popperProps={{ position: 'right' }} + onSelect={onSelect2} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( + <MenuToggle + ref={toggleRef} + isExpanded={isOpen2} + onClick={onToggle2} + variant="plain" + aria-label="Data list width modifiers example kebab toggle 2" + icon={<EllipsisVIcon />} + /> + )} + isOpen={isOpen2} + onOpenChange={(isOpen: boolean) => setIsOpen2(isOpen)} + > + <DropdownList> + <DropdownItem key="action2">Action</DropdownItem> + {/* Prevent default onClick functionality for example + purposes */} + <DropdownItem key="link2" to="#" onClick={(event: any) => event.preventDefault()}> + Link + </DropdownItem> + <DropdownItem key="disabled action2" isDisabled> + Disabled Action + </DropdownItem> + <DropdownItem + key="disabled link2" + isDisabled + to="#" + onClick={(event: any) => event.preventDefault()} + > + Disabled Link + </DropdownItem> + </DropdownList> + </Dropdown> + </DataListAction> + </DataListItemRow> + <DataListContent aria-label="Primary Content Details" id="width-ex3-expand1" isHidden={!show}> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. + </p> + </DataListContent> + </DataListItem> + </DataList> + </div> + </> + ); +}; diff --git a/packages/react-core/src/components/DatePicker/DatePicker.tsx b/packages/react-core/src/components/DatePicker/DatePicker.tsx index b528c070587..652310fed6f 100644 --- a/packages/react-core/src/components/DatePicker/DatePicker.tsx +++ b/packages/react-core/src/components/DatePicker/DatePicker.tsx @@ -1,54 +1,90 @@ -import * as React from 'react'; +import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DatePicker/date-picker'; -import buttonStyles from '@patternfly/react-styles/css/components/Button/button'; +import calendarMonthStyles from '@patternfly/react-styles/css/components/CalendarMonth/calendar-month'; import { TextInput, TextInputProps } from '../TextInput/TextInput'; +import { Button } from '../Button'; import { Popover, PopoverProps } from '../Popover/Popover'; -import { InputGroup } from '../InputGroup/InputGroup'; +import { InputGroup, InputGroupItem } from '../InputGroup'; import OutlinedCalendarAltIcon from '@patternfly/react-icons/dist/esm/icons/outlined-calendar-alt-icon'; -import { CalendarMonth, CalendarFormat, isValidDate } from '../CalendarMonth'; -import { useImperativeHandle } from 'react'; +import { CalendarMonth, CalendarFormat } from '../CalendarMonth'; +import { KeyTypes } from '../../helpers'; +import { isValidDate } from '../../helpers/datetimeUtils'; +import { HelperText, HelperTextItem } from '../HelperText'; +import cssFormControlWidthChars from '@patternfly/react-tokens/dist/esm/c_date_picker__input_c_form_control_width_chars'; + +/** Props that customize the requirement of a date */ +export interface DatePickerRequiredObject { + /** Flag indicating the date is required. */ + isRequired?: boolean; + /** Error message to display when the text input is empty and the isRequired prop is also passed in. */ + emptyDateText?: string; +} + +/** The main date picker component. */ export interface DatePickerProps - extends CalendarFormat, + extends + CalendarFormat, Omit<React.HTMLProps<HTMLInputElement>, 'onChange' | 'onFocus' | 'onBlur' | 'disabled' | 'ref'> { - /** Additional classes added to the date time picker. */ - className?: string; - /** Accessible label for the date picker */ + /** The container to append the menu to. Defaults to 'inline'. + * If your menu is being cut off you can append it to an element higher up the DOM tree. + * Some examples: + * menuAppendTo={() => document.body}; + * menuAppendTo={document.getElementById('target')} + */ + appendTo?: HTMLElement | ((ref?: HTMLElement) => HTMLElement) | 'inline'; + /** Accessible label for the date picker. */ 'aria-label'?: string; - /** How to format the date in the TextInput */ + /** Accessible label for the button to open the date picker. */ + buttonAriaLabel?: string; + /** Additional classes added to the date picker. */ + className?: string; + /** How to format the date in the text input. */ dateFormat?: (date: Date) => string; - /** How to format the date in the TextInput */ + /** How to parse the date in the text input. */ dateParse?: (value: string) => Date; - /** Flag indicating the date picker is disabled*/ + /** Helper text to display alongside the date picker. Expects a HelperText component. */ + helperText?: React.ReactNode; + /** Additional props for the text input. */ + inputProps?: TextInputProps; + /** Flag indicating the date picker is disabled. */ isDisabled?: boolean; - /** String to display in the empty date picker field as a hint for the expected date format */ - placeholder?: string; - /** Value of TextInput */ - value?: string; - /** Error message to display when the TextInput cannot be parsed. */ + /** Error message to display when the text input contains a non-empty value in an invalid format. */ invalidFormatText?: string; - /** Callback called every time the input value changes */ - onChange?: (value: string, date?: Date) => void; - /** Text for label */ - helperText?: React.ReactNode; - /** Aria label for the button to open the date picker */ - buttonAriaLabel?: string; - /** The element to append the popover to */ - appendTo?: HTMLElement | ((ref?: HTMLElement) => HTMLElement); - /** Props to pass to the Popover */ - popoverProps?: Omit<PopoverProps, 'appendTo'>; - /** Functions that returns an error message if a date is invalid */ + /** Callback called every time the text input loses focus. */ + onBlur?: (event: any, value: string, date?: Date) => void; + /** Callback called every time the text input value changes. */ + onChange?: (event: React.FormEvent<HTMLInputElement>, value: string, date?: Date) => void; + /** String to display in the empty text input as a hint for the expected date format. */ + placeholder?: string; + /** Props to pass to the popover that contains the calendar month component. */ + popoverProps?: Partial<Omit<PopoverProps, 'appendTo'>>; + /** Options to customize the requirement of a date */ + requiredDateOptions?: DatePickerRequiredObject; + /** Functions that returns an error message if a date is invalid. */ validators?: ((date: Date) => string)[]; - /** Additional props for input field */ - inputProps?: TextInputProps; + /** Value of the text input. */ + value?: string; } +/** Allows finer control over the calendar's open state when a React ref is passed into the + * date picker component. Accessed via ref.current[property], e.g. ref.current.toggleCalendar(). + */ + export interface DatePickerRef { - /** Sets the calendar open status */ + /** Current calendar open status. */ + isCalendarOpen: boolean; + /** Sets the calendar open status. */ setCalendarOpen: (isOpen: boolean) => void; - /** Toggles the calendar open status */ - toggleCalendar: () => void; + /** Toggles the calendar open status. If no parameters are passed, the calendar will simply + * toggle its open status. + * If the isOpen parameter is passed, that will set the calendar open status to the value + * of the isOpen parameter. + * If the eventKey parameter is set to 'Escape', that will invoke the date pickers + * onEscapePress event to toggle the correct control appropriately. + */ + toggleCalendar: (isOpen?: boolean) => void; } export const yyyyMMddFormat = (date: Date) => @@ -62,16 +98,18 @@ const DatePickerBase = ( className, locale = undefined, dateFormat = yyyyMMddFormat, - dateParse = (val: string) => val.split('-').length === 3 && new Date(`${val}T00:00:00`), + dateParse = (val: string) => (val.split('-').length === 3 ? new Date(`${val}T00:00:00`) : new Date(undefined)), isDisabled = false, placeholder = 'YYYY-MM-DD', value: valueProp = '', 'aria-label': ariaLabel = 'Date picker', buttonAriaLabel = 'Toggle date picker', onChange = (): any => undefined, + onBlur = (): any => undefined, invalidFormatText = 'Invalid date', + requiredDateOptions, helperText, - appendTo, + appendTo = 'inline', popoverProps, monthFormat, weekdayFormat, @@ -86,61 +124,94 @@ const DatePickerBase = ( }: DatePickerProps, ref: React.Ref<DatePickerRef> ) => { - const [value, setValue] = React.useState(valueProp); - const [valueDate, setValueDate] = React.useState(dateParse(value)); - const [errorText, setErrorText] = React.useState(''); - const [popoverOpen, setPopoverOpen] = React.useState(false); - const [selectOpen, setSelectOpen] = React.useState(false); - const [pristine, setPristine] = React.useState(true); - const widthChars = React.useMemo(() => Math.max(dateFormat(new Date()).length, placeholder.length), [dateFormat]); - const style = { '--pf-c-date-picker__input--c-form-control--width-chars': widthChars, ...styleProps }; - const buttonRef = React.useRef<HTMLButtonElement>(); - - React.useEffect(() => { + const [value, setValue] = useState(valueProp); + const [valueDate, setValueDate] = useState(dateParse(value)); + const [errorText, setErrorText] = useState(''); + const [popoverOpen, setPopoverOpen] = useState(false); + const [selectOpen, setSelectOpen] = useState(false); + const [pristine, setPristine] = useState(true); + const [textInputFocused, setTextInputFocused] = useState(false); + const widthChars = useMemo(() => Math.max(dateFormat(new Date()).length, placeholder.length), [dateFormat]); + const style = { [cssFormControlWidthChars.name]: widthChars, ...styleProps }; + const buttonRef = useRef<HTMLButtonElement>(undefined); + const datePickerWrapperRef = useRef<HTMLDivElement>(undefined); + const triggerRef = useRef<HTMLDivElement>(undefined); + const dateIsRequired = requiredDateOptions?.isRequired || false; + const emptyDateText = requiredDateOptions?.emptyDateText || 'Date cannot be blank'; + + useEffect(() => { setValue(valueProp); setValueDate(dateParse(valueProp)); }, [valueProp]); - const setError = (date: Date) => setErrorText(validators.map(validator => validator(date)).join('\n') || ''); + useEffect(() => { + if (isValidDate(valueDate)) { + applyValidators(valueDate); + } + }, [validators]); + + useEffect(() => { + setPristine(!value); + const newValueDate = dateParse(value); + if (errorText && isValidDate(newValueDate)) { + applyValidators(newValueDate); + } + if (value === '' && !pristine && !textInputFocused) { + dateIsRequired ? setErrorText(emptyDateText) : setErrorText(''); + } + }, [value]); + + const applyValidators = (date: Date) => { + const validatorResults = validators.map((validator) => validator(date)); + const validatorsToApply = validatorResults.filter((validator) => validator !== ''); + setErrorText(validatorsToApply.join('\n') || ''); + }; - const onTextInput = (value: string) => { - setPristine(false); + const onTextInput = (event: React.FormEvent<HTMLInputElement>, value: string) => { setValue(value); setErrorText(''); const newValueDate = dateParse(value); setValueDate(newValueDate); if (isValidDate(newValueDate)) { - onChange(value, new Date(newValueDate)); + onChange(event, value, new Date(newValueDate)); } else { - onChange(value); + onChange(event, value); } }; - const onInputBlur = () => { - if (pristine) { - return; - } + const onInputBlur = (event: any) => { + setTextInputFocused(false); const newValueDate = dateParse(value); - if (isValidDate(newValueDate)) { - setError(newValueDate); - } else { + const dateIsValid = isValidDate(newValueDate); + const onBlurDateArg = dateIsValid ? new Date(newValueDate) : undefined; + onBlur(event, value, onBlurDateArg); + + if (dateIsValid) { + applyValidators(newValueDate); + } + + if (!dateIsValid && !pristine) { setErrorText(invalidFormatText); } + + if (!dateIsValid && pristine && requiredDateOptions?.isRequired) { + setErrorText(emptyDateText); + } }; - const onDateClick = (newValueDate: Date) => { + const onDateClick = (_event: React.MouseEvent<HTMLButtonElement, MouseEvent>, newValueDate: Date) => { const newValue = dateFormat(newValueDate); setValue(newValue); setValueDate(newValueDate); - setError(newValueDate); + applyValidators(newValueDate); setPopoverOpen(false); - onChange(newValue, new Date(newValueDate)); + onChange(null, newValue, new Date(newValueDate)); }; const onKeyPress = (ev: React.KeyboardEvent<HTMLInputElement>) => { if (ev.key === 'Enter' && value) { if (isValidDate(valueDate)) { - setError(valueDate); + applyValidators(valueDate); } else { setErrorText(invalidFormatText); } @@ -151,14 +222,41 @@ const DatePickerBase = ( ref, () => ({ setCalendarOpen: (isOpen: boolean) => setPopoverOpen(isOpen), - toggleCalendar: () => setPopoverOpen(prev => !prev) + toggleCalendar: (setOpen?: boolean) => { + setPopoverOpen((prev) => (setOpen !== undefined ? setOpen : !prev)); + }, + isCalendarOpen: popoverOpen }), - [setPopoverOpen] + [setPopoverOpen, popoverOpen, selectOpen] ); + const createFocusSelectorString = (modifierClass: string) => + `.${calendarMonthStyles.calendarMonthDatesCell}.${modifierClass} .${calendarMonthStyles.calendarMonthDate}`; + const focusSelectorForSelectedDate = createFocusSelectorString(calendarMonthStyles.modifiers.selected); + const focusSelectorForSelectedEndRangeDate = createFocusSelectorString( + `${calendarMonthStyles.modifiers.selected}.${calendarMonthStyles.modifiers.endRange}` + ); + const focusSelectorForUnselectedDate = createFocusSelectorString(calendarMonthStyles.modifiers.current); + + /** + * Returns a CSS selector for a date button element which will receive initial focus after opening calendar popover. + * In case of a range picker it returns the end date, if it is selected, start date otherwise. + * In case of a normal datepicker it returns the selected date, if present, today otherwise. + */ + const getElementSelectorToFocus = () => { + if (isValidDate(valueDate) && isValidDate(rangeStart)) { + return focusSelectorForSelectedEndRangeDate; + } + if (isValidDate(valueDate) || isValidDate(rangeStart)) { + return focusSelectorForSelectedDate; + } + return focusSelectorForUnselectedDate; + }; + return ( - <div className={css(styles.datePicker, className)} style={style} {...props}> + <div className={css(styles.datePicker, className)} ref={datePickerWrapperRef} style={style} {...props}> <Popover + elementToFocus={getElementSelectorToFocus()} position="bottom" bodyContent={ <CalendarMonth @@ -166,8 +264,8 @@ const DatePickerBase = ( onChange={onDateClick} locale={locale} // Use truthy values of strings - validators={validators.map(validator => (date: Date) => !validator(date))} - onSelectToggle={open => setSelectOpen(open)} + validators={validators.map((validator) => (date: Date) => !validator(date))} + onSelectToggle={(open) => setSelectOpen(open)} monthFormat={monthFormat} weekdayFormat={weekdayFormat} longWeekdayFormat={longWeekdayFormat} @@ -178,56 +276,84 @@ const DatePickerBase = ( } showClose={false} isVisible={popoverOpen} - shouldClose={(_1, _2, event) => { + shouldClose={(event, hideFunction) => { event = event as KeyboardEvent; - // Let the select menu close - if (event.keyCode && event.keyCode === 27 && selectOpen) { + if (event.key === KeyTypes.Escape && selectOpen) { + event.stopPropagation(); + setSelectOpen(false); return false; } // Let our button handle toggling if (buttonRef.current && buttonRef.current.contains(event.target as Node)) { return false; } - setPopoverOpen(false); + + if (popoverOpen) { + event.stopPropagation(); + setPopoverOpen(false); + hideFunction(); + // If datepicker is required and the popover is opened without the text input + // first receiving focus, we want to validate that the text input is not blank upon + // closing the popover + requiredDateOptions?.isRequired && !value && setErrorText(emptyDateText); + } + if (event.key === KeyTypes.Escape && popoverOpen) { + event.stopPropagation(); + } return true; }} withFocusTrap hasNoPadding hasAutoWidth appendTo={appendTo} + triggerRef={triggerRef} {...popoverProps} > - <div className={styles.datePickerInput}> + <div className={styles.datePickerInput} ref={triggerRef}> <InputGroup> - <TextInput - isDisabled={isDisabled} - aria-label={ariaLabel} - placeholder={placeholder} - validated={errorText ? 'error' : 'default'} - value={value} - onChange={onTextInput} - onBlur={onInputBlur} - onKeyPress={onKeyPress} - {...inputProps} - /> - <button - ref={buttonRef} - className={css(buttonStyles.button, buttonStyles.modifiers.control)} - aria-label={buttonAriaLabel} - type="button" - onClick={() => setPopoverOpen(!popoverOpen)} - disabled={isDisabled} - > - <OutlinedCalendarAltIcon /> - </button> + <InputGroupItem> + <TextInput + isDisabled={isDisabled} + isRequired={requiredDateOptions?.isRequired} + aria-label={ariaLabel} + placeholder={placeholder} + validated={errorText.trim() ? 'error' : 'default'} + value={value} + onChange={onTextInput} + onBlur={onInputBlur} + onFocus={() => setTextInputFocused(true)} + onKeyPress={onKeyPress} + {...inputProps} + /> + </InputGroupItem> + <InputGroupItem> + <Button + ref={buttonRef} + variant="control" + aria-label={buttonAriaLabel} + onClick={() => setPopoverOpen(!popoverOpen)} + isDisabled={isDisabled} + icon={<OutlinedCalendarAltIcon />} + aria-haspopup="dialog" + /> + </InputGroupItem> </InputGroup> </div> </Popover> - {helperText && <div className={styles.datePickerHelperText}>{helperText}</div>} - {errorText.trim() && <div className={css(styles.datePickerHelperText, styles.modifiers.error)}>{errorText}</div>} + {(errorText || helperText) && ( + <div className={styles.datePickerHelperText}> + {errorText ? ( + <HelperText> + <HelperTextItem variant="error">{errorText}</HelperTextItem> + </HelperText> + ) : ( + helperText + )} + </div> + )} </div> ); }; -export const DatePicker = React.forwardRef<DatePickerRef, DatePickerProps>(DatePickerBase); -DatePicker.displayName = 'DatePickerBase'; +export const DatePicker = forwardRef<DatePickerRef, DatePickerProps>(DatePickerBase); +DatePicker.displayName = 'DatePicker'; diff --git a/packages/react-core/src/components/DatePicker/__tests__/DatePicker.test.tsx b/packages/react-core/src/components/DatePicker/__tests__/DatePicker.test.tsx index 7806a913080..4225fee64e4 100644 --- a/packages/react-core/src/components/DatePicker/__tests__/DatePicker.test.tsx +++ b/packages/react-core/src/components/DatePicker/__tests__/DatePicker.test.tsx @@ -1,8 +1,220 @@ -import { mount } from 'enzyme'; +import { screen, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { HelperText, HelperTextItem } from '../../HelperText'; import { DatePicker } from '../DatePicker'; -import React from 'react'; + +jest.mock('../../../helpers/util.ts'); test('disabled date picker', () => { - const view = mount(<DatePicker value="2020-11-20" isDisabled aria-label="disabled date picker" />); - expect(view.find('input')).toMatchSnapshot(); + const { asFragment } = render(<DatePicker value="2020-11-20" isDisabled aria-label="disabled date picker" />); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Does not render aria-invalid input when multiple validators return empty strings', async () => { + const user = userEvent.setup(); + + const rangeValidator = (_date: Date) => ''; + const rangeValidatorB = (_date: Date) => ''; + render(<DatePicker value="2020-03-17" validators={[rangeValidator, rangeValidatorB]} />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + expect(screen.getByRole('textbox')).not.toBeInvalid(); +}); + +test('Does not render helper text when multiple validators return empty strings', async () => { + const user = userEvent.setup(); + + const rangeValidator = (_date: Date) => ''; + const rangeValidatorB = (_date: Date) => ''; + render(<DatePicker value="2020-03-17" validators={[rangeValidator, rangeValidatorB]} />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.queryByText(': error status;')).not.toBeInTheDocument(); +}); + +test('Renders helper text when at least 1 validator returns a string', async () => { + const user = userEvent.setup(); + + const rangeValidator = (_date: Date) => 'Some error.'; + const rangeValidatorB = (_date: Date) => ''; + render(<DatePicker value="2020-03-17" validators={[rangeValidator, rangeValidatorB]} />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.getByText('Some error.')).toBeVisible(); + expect(screen.getByText(': error status;')).toBeInTheDocument(); +}); + +test('Renders helper text when more than 1 validator returns a string', async () => { + const user = userEvent.setup(); + + const rangeValidator = (_date: Date) => 'Some error.'; + const rangeValidatorB = (_date: Date) => 'Another error.'; + render(<DatePicker value="2020-03-17" validators={[rangeValidator, rangeValidatorB]} />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.getByText('Some error. Another error.')).toBeVisible(); + expect(screen.getByText(': error status;')).toBeInTheDocument(); +}); + +test('Error state can be cleared from outside', async () => { + const rangeValidator = (date: Date) => { + if (date < new Date('2020-03-17')) { + return 'error'; + } + return ''; + }; + + const user = userEvent.setup(); + + const { rerender } = render(<DatePicker value="2020-03-17" validators={[rangeValidator]} />); + + await user.clear(screen.getByRole('textbox')); + await user.type(screen.getByRole('textbox'), '2020-03-16'); + + await user.click(document.body); + + rerender(<DatePicker value="2020-03-18" validators={[rangeValidator]} />); + + expect(screen.getByRole('textbox')).not.toBeInvalid(); +}); + +test('With popover opened', async () => { + const user = userEvent.setup(); + + const { asFragment } = render(<DatePicker value="2020-03-17" />); + + await user.click(screen.getByRole('button', { name: 'Toggle date picker' })); + await screen.findByRole('button', { name: 'Previous month' }); + + expect(asFragment()).toMatchSnapshot(); +}); + +test('Shows helperText instead of "Invalid date" when no error exists', () => { + render( + <DatePicker + helperText={ + <HelperText> + <HelperTextItem>Help me</HelperTextItem> + </HelperText> + } + /> + ); + + expect(screen.queryByText('Invalid date')).not.toBeInTheDocument(); + expect(screen.getByText('Help me')).toBeVisible(); +}); + +test('Shows "Invalid date" instead of helperText when text input contains invalid date', async () => { + const user = userEvent.setup(); + + render( + <DatePicker + helperText={ + <HelperText> + <HelperTextItem>Help me</HelperTextItem> + </HelperText> + } + /> + ); + + await user.type(screen.getByRole('textbox'), 'not a date'); + await user.click(document.body); + + expect(screen.queryByText('Help me')).not.toBeInTheDocument(); + expect(screen.getByText('Invalid date')).toBeVisible(); +}); + +test('Does not render text input as invalid when requiredDateOptions.isRequired is false', async () => { + const user = userEvent.setup(); + + render(<DatePicker />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.getByRole('textbox')).not.toHaveAttribute('aria-invalid', 'true'); +}); + +test('Does not render emptyDateText when requiredDateOptions.isRequired is false', async () => { + const user = userEvent.setup(); + + render(<DatePicker />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.queryByText('Date cannot be blank')).not.toBeInTheDocument(); +}); + +test('Renders text input as invalid on blur when requiredDateOptions.isRequired is true', async () => { + const user = userEvent.setup(); + + render(<DatePicker requiredDateOptions={{ isRequired: true }} />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.getByRole('textbox')).toHaveAttribute('aria-invalid', 'true'); +}); + +test('Renders default emptyDateText on blur when requiredDateOptions.isRequired is true', async () => { + const user = userEvent.setup(); + + render(<DatePicker requiredDateOptions={{ isRequired: true }} />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.getByText('Date cannot be blank')).toBeInTheDocument(); +}); + +test('Renders custom emptyDateText when requiredDateOptions.isRequired is true', async () => { + const user = userEvent.setup(); + + render(<DatePicker requiredDateOptions={{ isRequired: true, emptyDateText: 'Required in test' }} />); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.getByText('Required in test')).toBeInTheDocument(); +}); + +test('Shows emptyDateText instead of helperText when text input is empty and requiredDateOptions.isRequired is true', async () => { + const user = userEvent.setup(); + + render( + <DatePicker + requiredDateOptions={{ isRequired: true }} + helperText={ + <HelperText> + <HelperTextItem>Help me</HelperTextItem> + </HelperText> + } + /> + ); + + await user.click(screen.getByRole('textbox')); + await user.click(document.body); + + expect(screen.queryByText('Help me')).not.toBeInTheDocument(); + expect(screen.getByText('Date cannot be blank')).toBeVisible(); +}); + +test('Renders text input as invalid when requiredDateOptions.isRequired is true and popover is closed without selection', async () => { + const user = userEvent.setup(); + + render(<DatePicker requiredDateOptions={{ isRequired: true }} />); + + await user.click(screen.getByRole('button', { name: 'Toggle date picker' })); + await user.click(document.body); + + expect(screen.getByRole('textbox')).toHaveAttribute('aria-invalid', 'true'); }); diff --git a/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap b/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap index da981bd4bde..591e035d533 100644 --- a/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap +++ b/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap @@ -1,22 +1,897 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`With popover opened 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-date-picker" + style="--pf-v6-c-date-picker__input--c-form-control--width-chars: 10;" + > + <div + class="pf-v6-c-date-picker__input" + > + <div + class="pf-v6-c-input-group" + > + <div + class="pf-v6-c-input-group__item" + > + <span + class="pf-v6-c-form-control" + > + <input + aria-invalid="false" + aria-label="Date picker" + data-ouia-component-id="OUIA-Generated-TextInputBase-:rq:" + data-ouia-component-type="PF6/TextInput" + data-ouia-safe="true" + placeholder="YYYY-MM-DD" + type="text" + value="2020-03-17" + /> + </span> + </div> + <div + class="pf-v6-c-input-group__item" + > + <button + aria-haspopup="dialog" + aria-label="Toggle date picker" + class="pf-v6-c-button pf-m-control" + data-ouia-component-id="OUIA-Generated-Button-control-:rr:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" + > + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + width="1em" + > + <svg + class="pf-v6-icon-default" + viewBox="0 0 448 512" + > + <path + d="M148 288h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm108-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm96 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm-96 96v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm-96 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm96-260v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48zm-48 346V160H48v298c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z" + /> + </svg> + <svg + class="pf-v6-icon-rh-ui" + viewBox="0 0 32 32" + > + <path + d="M28.5 5H23V3a1 1 0 1 0-2 0v2H11V3a1 1 0 1 0-2 0v2H3.507c-.827 0-1.5.673-1.5 1.5v7c0 .01.003.019.003.029v8.423c0 .017-.01.031-.01.048 0 .279.115.53.299.712l.004.005 6.99 6.99c.092.092.201.165.323.216l.005.002c.121.05.25.076.38.076h18.5c.827 0 1.5-.673 1.5-1.5V6.5c0-.827-.673-1.5-1.5-1.5ZM9 7v2a1 1 0 1 0 2 0V7h10v2a1 1 0 1 0 2 0V7h5v6H4.01V7H9Zm0 19.586L5.414 23H9v3.586ZM11 28v-5.5c0-.827-.673-1.5-1.5-1.5H4.01v-6H28v13H11Z" + /> + </svg> + </svg> + </span> + </button> + </div> + </div> + </div> + <div + aria-describedby="popover-pf-:ro:-body" + aria-label="" + aria-modal="true" + class="pf-v6-c-popover pf-m-no-padding pf-m-width-auto pf-m-bottom" + data-popper-escaped="true" + data-popper-placement="bottom" + data-popper-reference-hidden="true" + role="dialog" + style="position: absolute; left: 0px; top: 0px; z-index: 9999; opacity: 1; transition: opacity 300ms cubic-bezier(.54, 1.5, .38, 1.11); min-width: auto; transform: translate(0px, 25px);" + > + <div + class="pf-v6-c-popover__arrow" + /> + <div + class="pf-v6-c-popover__content" + > + <div + class="pf-v6-c-popover__body" + id="popover-pf-:ro:-body" + > + <div + class="pf-v6-c-calendar-month" + > + <div + class="pf-v6-c-calendar-month__header" + > + <div + class="pf-v6-c-calendar-month__header-nav-control pf-m-prev-month" + > + <button + aria-label="Previous month" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:rt:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" + > + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" + > + <path + d="m6.41 10 7.29-7.29.02-.02c.38-.4.37-1.03-.02-1.41-.4-.38-1.03-.37-1.41.02L4.64 8.95a1.49 1.49 0 0 0 0 2.12l7.65 7.65c.19.19.44.29.71.29.27 0 .52-.11.71-.29a.996.996 0 0 0 0-1.41l-7.29-7.29Z" + /> + </svg> + </span> + </button> + </div> + <div + class="pf-v6-c-input-group" + > + <div + class="pf-v6-c-input-group__item pf-m-fill" + > + <div + class="pf-v6-c-calendar-month__header-month" + > + <span + hidden="" + id="hidden-month-span:rs:" + > + Month + </span> + <button + aria-expanded="false" + class="pf-v6-c-menu-toggle" + data-ouia-component-id="OUIA-Generated-MenuToggle-:r10:" + data-ouia-component-type="PF6/MenuToggle" + data-ouia-safe="true" + style="width: 140px;" + type="button" + > + <span + class="pf-v6-c-menu-toggle__text" + > + March + </span> + <span + class="pf-v6-c-menu-toggle__controls" + > + <span + class="pf-v6-c-menu-toggle__toggle-icon" + > + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + width="1em" + > + <svg + class="pf-v6-icon-default" + viewBox="0 0 320 512" + > + <path + d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" + /> + </svg> + <svg + class="pf-v6-icon-rh-ui" + viewBox="0 0 32 32" + > + <path + d="M16 24.792c-.384 0-.769-.146-1.061-.438L2.293 11.707a.999.999 0 1 1 1.414-1.414L16 22.586l12.293-12.293a.999.999 0 1 1 1.414 1.414L17.061 24.353a1.497 1.497 0 0 1-1.061.438Z" + /> + </svg> + </svg> + </span> + </span> + </button> + </div> + </div> + <div + class="pf-v6-c-input-group__item" + > + <div + class="pf-v6-c-calendar-month__header-year" + > + <span + class="pf-v6-c-form-control" + > + <input + aria-invalid="false" + aria-label="Select year" + data-ouia-component-id="OUIA-Generated-TextInputBase-:r12:" + data-ouia-component-type="PF6/TextInput" + data-ouia-safe="true" + type="number" + value="2020" + /> + </span> + </div> + </div> + </div> + <div + class="pf-v6-c-calendar-month__header-nav-control pf-m-next-month" + > + <button + aria-label="Next month" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:r13:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" + > + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" + > + <path + d="M14.35 8.94 6.71 1.29l-.02-.02c-.4-.38-1.03-.37-1.41.02-.38.4-.37 1.03.02 1.41l7.29 7.29-7.29 7.29a1.003 1.003 0 0 0 1.42 1.42l7.65-7.65c.59-.59.59-1.54 0-2.12Z" + /> + </svg> + </span> + </button> + </div> + </div> + <table + class="pf-v6-c-calendar-month__calendar" + > + <thead + class="pf-v6-c-calendar-month__days" + > + <tr> + <th + class="pf-v6-c-calendar-month__day" + scope="col" + > + <span + class="pf-v6-screen-reader" + > + Sunday + </span> + <span + aria-hidden="true" + > + S + </span> + </th> + <th + class="pf-v6-c-calendar-month__day" + scope="col" + > + <span + class="pf-v6-screen-reader" + > + Monday + </span> + <span + aria-hidden="true" + > + M + </span> + </th> + <th + class="pf-v6-c-calendar-month__day" + scope="col" + > + <span + class="pf-v6-screen-reader" + > + Tuesday + </span> + <span + aria-hidden="true" + > + T + </span> + </th> + <th + class="pf-v6-c-calendar-month__day" + scope="col" + > + <span + class="pf-v6-screen-reader" + > + Wednesday + </span> + <span + aria-hidden="true" + > + W + </span> + </th> + <th + class="pf-v6-c-calendar-month__day" + scope="col" + > + <span + class="pf-v6-screen-reader" + > + Thursday + </span> + <span + aria-hidden="true" + > + T + </span> + </th> + <th + class="pf-v6-c-calendar-month__day" + scope="col" + > + <span + class="pf-v6-screen-reader" + > + Friday + </span> + <span + aria-hidden="true" + > + F + </span> + </th> + <th + class="pf-v6-c-calendar-month__day" + scope="col" + > + <span + class="pf-v6-screen-reader" + > + Saturday + </span> + <span + aria-hidden="true" + > + S + </span> + </th> + </tr> + </thead> + <tbody> + <tr + class="pf-v6-c-calendar-month__dates-row" + > + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="1 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 1 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="2 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 2 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="3 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 3 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="4 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 4 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="5 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 5 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="6 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 6 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="7 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 7 + </button> + </td> + </tr> + <tr + class="pf-v6-c-calendar-month__dates-row" + > + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="8 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 8 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="9 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 9 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="10 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 10 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="11 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 11 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="12 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 12 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="13 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 13 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="14 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 14 + </button> + </td> + </tr> + <tr + class="pf-v6-c-calendar-month__dates-row" + > + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="15 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 15 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="16 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 16 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell pf-m-selected" + > + <button + aria-label="17 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="0" + type="button" + > + 17 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="18 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 18 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="19 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 19 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="20 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 20 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="21 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 21 + </button> + </td> + </tr> + <tr + class="pf-v6-c-calendar-month__dates-row" + > + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="22 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 22 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="23 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 23 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="24 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 24 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="25 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 25 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="26 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 26 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="27 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 27 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="28 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 28 + </button> + </td> + </tr> + <tr + class="pf-v6-c-calendar-month__dates-row" + > + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="29 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 29 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="30 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 30 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell" + > + <button + aria-label="31 March 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 31 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell pf-m-adjacent-month" + > + <button + aria-label="1 April 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 1 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell pf-m-adjacent-month" + > + <button + aria-label="2 April 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 2 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell pf-m-adjacent-month" + > + <button + aria-label="3 April 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 3 + </button> + </td> + <td + class="pf-v6-c-calendar-month__dates-cell pf-m-adjacent-month" + > + <button + aria-label="4 April 2020" + class="pf-v6-c-calendar-month__date" + tabindex="-1" + type="button" + > + 4 + </button> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </div> + </div> +</DocumentFragment> +`; + exports[`disabled date picker 1`] = ` -<input - aria-invalid={false} - aria-label="disabled date picker" - className="pf-c-form-control" - data-ouia-component-id="OUIA-Generated-TextInputBase-1" - data-ouia-component-type="PF4/TextInput" - data-ouia-safe={true} - disabled={true} - onBlur={[Function]} - onChange={[Function]} - onFocus={[Function]} - onKeyPress={[Function]} - placeholder="YYYY-MM-DD" - readOnly={false} - required={false} - type="text" - value="2020-11-20" -/> +<DocumentFragment> + <div + class="pf-v6-c-date-picker" + style="--pf-v6-c-date-picker__input--c-form-control--width-chars: 10;" + > + <div + class="pf-v6-c-date-picker__input" + > + <div + class="pf-v6-c-input-group" + > + <div + class="pf-v6-c-input-group__item" + > + <span + class="pf-v6-c-form-control pf-m-disabled" + > + <input + aria-invalid="false" + aria-label="disabled date picker" + data-ouia-component-id="OUIA-Generated-TextInputBase-:r2:" + data-ouia-component-type="PF6/TextInput" + data-ouia-safe="true" + disabled="" + placeholder="YYYY-MM-DD" + type="text" + value="2020-11-20" + /> + </span> + </div> + <div + class="pf-v6-c-input-group__item" + > + <button + aria-haspopup="dialog" + aria-label="Toggle date picker" + class="pf-v6-c-button pf-m-control" + data-ouia-component-id="OUIA-Generated-Button-control-:r3:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + disabled="" + type="button" + > + <span + class="pf-v6-c-button__icon" + > + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + width="1em" + > + <svg + class="pf-v6-icon-default" + viewBox="0 0 448 512" + > + <path + d="M148 288h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm108-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm96 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm-96 96v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm-96 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm96-260v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48zm-48 346V160H48v298c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z" + /> + </svg> + <svg + class="pf-v6-icon-rh-ui" + viewBox="0 0 32 32" + > + <path + d="M28.5 5H23V3a1 1 0 1 0-2 0v2H11V3a1 1 0 1 0-2 0v2H3.507c-.827 0-1.5.673-1.5 1.5v7c0 .01.003.019.003.029v8.423c0 .017-.01.031-.01.048 0 .279.115.53.299.712l.004.005 6.99 6.99c.092.092.201.165.323.216l.005.002c.121.05.25.076.38.076h18.5c.827 0 1.5-.673 1.5-1.5V6.5c0-.827-.673-1.5-1.5-1.5ZM9 7v2a1 1 0 1 0 2 0V7h10v2a1 1 0 1 0 2 0V7h5v6H4.01V7H9Zm0 19.586L5.414 23H9v3.586ZM11 28v-5.5c0-.827-.673-1.5-1.5-1.5H4.01v-6H28v13H11Z" + /> + </svg> + </svg> + </span> + </button> + </div> + </div> + </div> + </div> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DatePicker/examples/DatePicker.md b/packages/react-core/src/components/DatePicker/examples/DatePicker.md index 62a8404b04d..84f79c38e3b 100644 --- a/packages/react-core/src/components/DatePicker/examples/DatePicker.md +++ b/packages/react-core/src/components/DatePicker/examples/DatePicker.md @@ -1,154 +1,71 @@ --- id: Date picker section: components -cssPrefix: pf-c-date-picker -propComponents: ['DatePicker', 'CalendarFormat', 'DatePickerRef'] -beta: true +subsection: date-and-time +cssPrefix: pf-v6-c-date-picker +propComponents: ['DatePicker', 'CalendarFormat', 'DatePickerRef', 'DatePickerRequiredObject'] --- +import { Fragment, useState, useRef } from 'react'; + ## Examples + ### Basic -```js -import React from 'react'; -import { DatePicker } from '@patternfly/react-core'; -<DatePicker onChange={(str, date) => console.log('onChange', str, date)} /> +```ts file="./DatePickerBasic.tsx" + +``` + +### Required + +To require users to select a date before continuing, use the `requiredDateOptions.isRequired` property. + +A required date picker will be invalid when the text input is empty and either the text input loses focus or the date picker popover is closed. + +The error message can be customized via the `requiredDateOptions.emptyDateText` property. + +```ts file="./DatePickerRequired.tsx" + ``` ### American format -```js -import React from 'react'; -import { DatePicker } from '@patternfly/react-core'; - -AmericanFormat = () => { - const dateFormat = date => date.toLocaleDateString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g,'-'); - const dateParse = date => { - const split = date.split('-'); - if (split.length !== 3) { - return new Date(); - } - let month = split[0]; - let day = split[1]; - let year = split[2]; - return new Date(`${year.padStart(4, '0')}-${month.padStart(2, '0')}-${day.padStart(2, '0')}T00:00:00`); - }; - - return ( - <DatePicker - value="03-05-2020" - placeholder="MM-DD-YYYY" - dateFormat={dateFormat} - dateParse={dateParse} - /> - ); -} + +```ts file="./DatePickerAmerican.tsx" + ``` ### Helper text -```js -import React from 'react'; -import { DatePicker } from '@patternfly/react-core'; -<DatePicker value="2020-03-05" helperText="Select a date." /> +```ts file="./DatePickerHelperText.tsx" + ``` ### Min and max date -```js -import React from 'react'; -import { DatePicker } from '@patternfly/react-core'; - -MinMaxDate = () => { - const minDate = new Date(2020, 2, 16); - const maxDate = new Date(2020, 2, 20); - const rangeValidator = date => { - if (date < minDate) { - return 'Date is before the allowable range.'; - } - else if (date > maxDate) { - return 'Date is after the allowable range.'; - } - - return ''; - }; - return <DatePicker value="2020-03-17" validators={[rangeValidator]} />; -} + +```ts file="./DatePickerMinMax.tsx" + ``` ### French -```js -import React from 'react'; -import { DatePicker, Weekday } from '@patternfly/react-core'; - -FrenchMinMaxDate = () => { - const minDate = new Date(2020, 2, 16); - const maxDate = new Date(2020, 2, 20); - const rangeValidator = date => { - if (date < minDate) { - return 'Cette date est antérieure à la première date valide.'; - } - else if (date > maxDate) { - return 'Cette date est postérieure à la dernière date valide.'; - } - - return ''; - }; - return ( - <DatePicker - value="2020-03-17" - validators={[rangeValidator]} - placeholder="aaaa-mm-jj" - invalidFormatText="Cette date est invalide." - locale="fr" - weekStart={Weekday.Monday} - /> - ); -} +```ts file="./DatePickerFrench.tsx" + ``` ### Controlled -```js -import React from 'react'; -import { Button, DatePicker } from '@patternfly/react-core'; - -ControlledDate = () => { - const initialValue = '2020-03-17'; - const [value, setValue] = React.useState(initialValue); - return ( - <React.Fragment> - <Button onClick={() => setValue(initialValue)}> - Reset date - </Button> - <DatePicker - value={value} - onChange={value => setValue(value)} - /> - </React.Fragment> - ); -} +```ts file="./DatePickerControlled.tsx" + +``` + +### Controlled required + +```ts file="./DatePickerControlledRequired.tsx" + ``` ### Controlling the date picker calendar state -```js -import React from 'react'; -import { Button, DatePicker } from '@patternfly/react-core'; - -ControllingDatePicker = () => { - const dateRef = React.useRef(null); - const onClick = () => { - if (dateRef.current) { - dateRef.current.toggleCalendar() - } - }; - return ( - <React.Fragment> - <Button onClick={onClick}> - Toggle calendar - </Button> - <DatePicker ref={ dateRef } /> - </React.Fragment> - ); -} +```ts file="./DatePickerControlledCalendar.tsx" + ``` diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerAmerican.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerAmerican.tsx new file mode 100644 index 00000000000..b41299b7368 --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerAmerican.tsx @@ -0,0 +1,18 @@ +import { DatePicker } from '@patternfly/react-core'; + +export const DatePickerAmerican: React.FunctionComponent = () => { + const dateFormat = (date: Date) => + date.toLocaleDateString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '-'); + const dateParse = (date: string) => { + const split = date.split('-'); + if (split.length !== 3) { + return new Date(); + } + const month = split[0]; + const day = split[1]; + const year = split[2]; + return new Date(`${year.padStart(4, '0')}-${month.padStart(2, '0')}-${day.padStart(2, '0')}T00:00:00`); + }; + + return <DatePicker value="03-05-2020" placeholder="MM-DD-YYYY" dateFormat={dateFormat} dateParse={dateParse} />; +}; diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerBasic.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerBasic.tsx new file mode 100644 index 00000000000..3008b7dc715 --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerBasic.tsx @@ -0,0 +1,10 @@ +import { DatePicker } from '@patternfly/react-core'; + +export const DatePickerBasic: React.FunctionComponent = () => ( + <DatePicker + // eslint-disable-next-line no-console + onBlur={(_event, str, date) => console.log('onBlur', str, date)} + // eslint-disable-next-line no-console + onChange={(_event, str, date) => console.log('onChange', str, date)} + /> +); diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerControlled.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerControlled.tsx new file mode 100644 index 00000000000..980df3fdf0f --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerControlled.tsx @@ -0,0 +1,22 @@ +import { Fragment, useState } from 'react'; +import { Button, DatePicker, Flex, FlexItem } from '@patternfly/react-core'; + +export const DatePickerControlled: React.FunctionComponent = () => { + const initialValue = '2020-03-17'; + const [value, setValue] = useState(initialValue); + return ( + <Fragment> + <DatePicker value={value} onChange={(_event, value) => setValue(value)} /> + <br /> + <br /> + <Flex> + <FlexItem> + <Button onClick={() => setValue(initialValue)}>Reset date</Button> + </FlexItem> + <FlexItem> + <Button onClick={() => setValue('')}>Clear date</Button> + </FlexItem> + </Flex> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerControlledCalendar.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerControlledCalendar.tsx new file mode 100644 index 00000000000..b7f7805fbf3 --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerControlledCalendar.tsx @@ -0,0 +1,19 @@ +import { Fragment, useRef } from 'react'; +import { Button, DatePicker } from '@patternfly/react-core'; + +export const DatePickerControlledCalendar: React.FunctionComponent = () => { + const dateRef = useRef(null); + const onClick = () => { + if (dateRef.current) { + dateRef.current.toggleCalendar(); + } + }; + return ( + <Fragment> + <DatePicker ref={dateRef} /> + <br /> + <br /> + <Button onClick={onClick}>Toggle calendar</Button> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerControlledRequired.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerControlledRequired.tsx new file mode 100644 index 00000000000..dc66819a833 --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerControlledRequired.tsx @@ -0,0 +1,26 @@ +import { Fragment, useState } from 'react'; +import { Button, DatePicker, Flex, FlexItem } from '@patternfly/react-core'; + +export const DatePickerControlled: React.FunctionComponent = () => { + const initialValue = '2020-03-17'; + const [value, setValue] = useState(initialValue); + return ( + <Fragment> + <DatePicker + requiredDateOptions={{ isRequired: true, emptyDateText: 'Date is required' }} + value={value} + onChange={(_event, value) => setValue(value)} + /> + <br /> + <br /> + <Flex> + <FlexItem> + <Button onClick={() => setValue(initialValue)}>Reset date</Button> + </FlexItem> + <FlexItem> + <Button onClick={() => setValue('')}>Clear date</Button> + </FlexItem> + </Flex> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerFrench.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerFrench.tsx new file mode 100644 index 00000000000..3006e3b235a --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerFrench.tsx @@ -0,0 +1,25 @@ +import { DatePicker, Weekday } from '@patternfly/react-core'; + +export const DatePickerFrench: React.FunctionComponent = () => { + const minDate = new Date(2020, 2, 16); + const maxDate = new Date(2020, 2, 20); + const rangeValidator = (date: Date) => { + if (date < minDate) { + return 'Cette date est antérieure à la première date valide.'; + } else if (date > maxDate) { + return 'Cette date est postérieure à la dernière date valide.'; + } + + return ''; + }; + return ( + <DatePicker + value="2020-03-17" + validators={[rangeValidator]} + placeholder="aaaa-mm-jj" + invalidFormatText="Cette date est invalide." + locale="fr" + weekStart={Weekday.Monday} + /> + ); +}; diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerHelperText.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerHelperText.tsx new file mode 100644 index 00000000000..55c280074fd --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerHelperText.tsx @@ -0,0 +1,12 @@ +import { DatePicker, HelperText, HelperTextItem } from '@patternfly/react-core'; + +export const DatePickerHelperText: React.FunctionComponent = () => ( + <DatePicker + value="2020-03-05" + helperText={ + <HelperText> + <HelperTextItem>Select a date.</HelperTextItem> + </HelperText> + } + /> +); diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerMinMax.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerMinMax.tsx new file mode 100644 index 00000000000..74f565bc37a --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerMinMax.tsx @@ -0,0 +1,16 @@ +import { DatePicker } from '@patternfly/react-core'; + +export const DatePickerMinMax: React.FunctionComponent = () => { + const minDate = new Date(2020, 2, 16); + const maxDate = new Date(2020, 2, 20); + const rangeValidator = (date: Date) => { + if (date < minDate) { + return 'Date is before the allowable range.'; + } else if (date > maxDate) { + return 'Date is after the allowable range.'; + } + + return ''; + }; + return <DatePicker value="2020-03-17" validators={[rangeValidator]} />; +}; diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerRequired.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerRequired.tsx new file mode 100644 index 00000000000..8571cd817d4 --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerRequired.tsx @@ -0,0 +1,5 @@ +import { DatePicker } from '@patternfly/react-core'; + +export const DatePickerRequired: React.FunctionComponent = () => ( + <DatePicker requiredDateOptions={{ isRequired: true, emptyDateText: 'Date is required' }} /> +); diff --git a/packages/react-core/src/components/DescriptionList/DescriptionList.tsx b/packages/react-core/src/components/DescriptionList/DescriptionList.tsx index a5513648b8f..1e957c597e9 100644 --- a/packages/react-core/src/components/DescriptionList/DescriptionList.tsx +++ b/packages/react-core/src/components/DescriptionList/DescriptionList.tsx @@ -1,9 +1,11 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; import { formatBreakpointMods } from '../../helpers'; +import cssGridTemplateColumnsMin from '@patternfly/react-tokens/dist/esm/c_description_list_GridTemplateColumns_min'; +import cssTermWidth from '@patternfly/react-tokens/dist/esm/c_description_list__term_width'; +import cssHorizontalTermWidth from '@patternfly/react-tokens/dist/esm/c_description_list_m_horizontal__term_width'; -export interface AutoFitModifiers { +export interface BreakpointModifiers { default?: string; md?: string; lg?: string; @@ -30,7 +32,9 @@ export interface DescriptionListProps extends Omit<React.HTMLProps<HTMLDListElem isFluid?: boolean; /** Sets the the default placement of description list groups to fill from top to bottom. */ isFillColumns?: boolean; - /** Sets the number of columns on the description list */ + /** Sets the display size of the descriptions in the description list.*/ + displaySize?: 'default' | 'lg' | '2xl'; + /** Sets the number of columns on the description list at various breakpoints */ columnModifier?: { default?: '1Col' | '2Col' | '3Col'; sm?: '1Col' | '2Col' | '3Col'; @@ -39,7 +43,7 @@ export interface DescriptionListProps extends Omit<React.HTMLProps<HTMLDListElem xl?: '1Col' | '2Col' | '3Col'; '2xl'?: '1Col' | '2Col' | '3Col'; }; - /** Indicates how the menu will align at screen size breakpoints. Default alignment is set via the position property. */ + /** Indicates how the menu will align at various breakpoints. */ orientation?: { sm?: 'vertical' | 'horizontal'; md?: 'vertical' | 'horizontal'; @@ -47,6 +51,7 @@ export interface DescriptionListProps extends Omit<React.HTMLProps<HTMLDListElem xl?: 'vertical' | 'horizontal'; '2xl'?: 'vertical' | 'horizontal'; }; + /** Sets the minimum column size for the auto-fit (isAutoFit) layout at various breakpoints. */ autoFitMinModifier?: { default?: string; sm?: string; @@ -55,11 +60,21 @@ export interface DescriptionListProps extends Omit<React.HTMLProps<HTMLDListElem xl?: string; '2xl'?: string; }; + /** Sets the description list's term column width.*/ + termWidth?: string; + /** Sets the horizontal description list's term column width at various breakpoints. */ + horizontalTermWidthModifier?: { + default?: string; + sm?: string; + md?: string; + lg?: string; + xl?: string; + '2xl'?: string; + }; } -const setAutoFitMinModifiers = (autoFitMinModifier: AutoFitModifiers) => { - const prefix = '--pf-c-description-list--GridTemplateColumns--min'; - const mods = autoFitMinModifier as Partial<{ [k: string]: string }>; +const setBreakpointModifiers = (prefix: string, modifiers: BreakpointModifiers) => { + const mods = modifiers as Partial<{ [k: string]: string }>; return Object.keys(mods || {}).reduce( (acc, curr) => curr === 'default' ? { ...acc, [prefix]: mods[curr] } : { ...acc, [`${prefix}-on-${curr}`]: mods[curr] }, @@ -77,35 +92,57 @@ export const DescriptionList: React.FunctionComponent<DescriptionListProps> = ({ isCompact, isFluid, isFillColumns, + displaySize = 'default', columnModifier, autoFitMinModifier, + termWidth, + horizontalTermWidthModifier, orientation, style, ...props -}: DescriptionListProps) => ( - <dl - className={css( - styles.descriptionList, - (isHorizontal || isFluid) && styles.modifiers.horizontal, - isAutoColumnWidths && styles.modifiers.autoColumnWidths, - isAutoFit && styles.modifiers.autoFit, - formatBreakpointMods(columnModifier, styles), - formatBreakpointMods(orientation, styles), - isInlineGrid && styles.modifiers.inlineGrid, - isCompact && styles.modifiers.compact, - isFluid && styles.modifiers.fluid, - isFillColumns && styles.modifiers.fillColumns, - className - )} - style={ - autoFitMinModifier || style - ? { ...(isAutoFit ? setAutoFitMinModifiers(autoFitMinModifier) : {}), ...style } - : undefined - } - {...props} - > - {children} - </dl> -); +}: DescriptionListProps) => { + if (isAutoFit && autoFitMinModifier) { + style = { + ...style, + ...setBreakpointModifiers(cssGridTemplateColumnsMin.name, autoFitMinModifier) + }; + } + if (termWidth) { + style = { + ...style, + ...{ [cssTermWidth.name]: termWidth } + }; + } + if (isHorizontal && horizontalTermWidthModifier) { + style = { + ...style, + ...setBreakpointModifiers(cssHorizontalTermWidth.name, horizontalTermWidthModifier) + }; + } + + return ( + <dl + className={css( + styles.descriptionList, + (isHorizontal || isFluid) && styles.modifiers.horizontal, + isAutoColumnWidths && styles.modifiers.autoColumnWidths, + isAutoFit && styles.modifiers.autoFit, + formatBreakpointMods(columnModifier, styles), + formatBreakpointMods(orientation, styles), + isInlineGrid && styles.modifiers.inlineGrid, + isCompact && styles.modifiers.compact, + isFluid && styles.modifiers.fluid, + isFillColumns && styles.modifiers.fillColumns, + displaySize === 'lg' && styles.modifiers.displayLg, + displaySize === '2xl' && styles.modifiers.display_2xl, + className + )} + style={style} + {...props} + > + {children} + </dl> + ); +}; DescriptionList.displayName = 'DescriptionList'; diff --git a/packages/react-core/src/components/DescriptionList/DescriptionListDescription.tsx b/packages/react-core/src/components/DescriptionList/DescriptionListDescription.tsx index 1bee65c930c..cb37fdf71c6 100644 --- a/packages/react-core/src/components/DescriptionList/DescriptionListDescription.tsx +++ b/packages/react-core/src/components/DescriptionList/DescriptionListDescription.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; import { css } from '@patternfly/react-styles'; @@ -15,7 +14,7 @@ export const DescriptionListDescription: React.FunctionComponent<DescriptionList ...props }: DescriptionListDescriptionProps) => ( <dd className={css(styles.descriptionListDescription, className)} {...props}> - <div className={'pf-c-description-list__text'}>{children}</div> + <div className={css(styles.descriptionListText)}>{children}</div> </dd> ); DescriptionListDescription.displayName = 'DescriptionListDescription'; diff --git a/packages/react-core/src/components/DescriptionList/DescriptionListGroup.tsx b/packages/react-core/src/components/DescriptionList/DescriptionListGroup.tsx index ad0062c0d58..1d4b54a3529 100644 --- a/packages/react-core/src/components/DescriptionList/DescriptionListGroup.tsx +++ b/packages/react-core/src/components/DescriptionList/DescriptionListGroup.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; import { css } from '@patternfly/react-styles'; @@ -9,7 +8,7 @@ export interface DescriptionListGroupProps extends React.HTMLProps<HTMLDivElemen className?: string; } -export const DescriptionListGroup: React.FC<DescriptionListGroupProps> = ({ +export const DescriptionListGroup: React.FunctionComponent<DescriptionListGroupProps> = ({ className, children, ...props @@ -18,4 +17,5 @@ export const DescriptionListGroup: React.FC<DescriptionListGroupProps> = ({ {children} </div> ); + DescriptionListGroup.displayName = 'DescriptionListGroup'; diff --git a/packages/react-core/src/components/DescriptionList/DescriptionListTerm.tsx b/packages/react-core/src/components/DescriptionList/DescriptionListTerm.tsx index a6aba53a310..3536e485dd8 100644 --- a/packages/react-core/src/components/DescriptionList/DescriptionListTerm.tsx +++ b/packages/react-core/src/components/DescriptionList/DescriptionListTerm.tsx @@ -1,10 +1,11 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; import { css } from '@patternfly/react-styles'; export interface DescriptionListTermProps extends React.HTMLProps<HTMLElement> { /** Anything that can be rendered inside of list term */ children: React.ReactNode; + /** Icon that is rendered inside of list term to the left side of the children */ + icon?: React.ReactNode; /** Additional classes added to the DescriptionListTerm */ className?: string; } @@ -12,9 +13,11 @@ export interface DescriptionListTermProps extends React.HTMLProps<HTMLElement> { export const DescriptionListTerm: React.FunctionComponent<DescriptionListTermProps> = ({ children, className, + icon, ...props }: DescriptionListTermProps) => ( <dt className={css(styles.descriptionListTerm, className)} {...props}> + {icon ? <span className={css(styles.descriptionListTermIcon)}>{icon}</span> : null} <span className={css(styles.descriptionListText)}>{children}</span> </dt> ); diff --git a/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpText.tsx b/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpText.tsx index cf273a9d504..2a21d37b9a2 100644 --- a/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpText.tsx +++ b/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpText.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; import { css } from '@patternfly/react-styles'; diff --git a/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpTextButton.tsx b/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpTextButton.tsx index cff5753ad72..6950498d2e9 100644 --- a/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpTextButton.tsx +++ b/packages/react-core/src/components/DescriptionList/DescriptionListTermHelpTextButton.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { createRef } from 'react'; import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; import { css } from '@patternfly/react-styles'; @@ -13,15 +13,33 @@ export const DescriptionListTermHelpTextButton: React.FunctionComponent<Descript children, className, ...props -}: DescriptionListTermHelpTextButtonProps) => ( - <span - className={css(className, styles.descriptionListText, styles.modifiers.helpText)} - role="button" - type="button" - tabIndex={0} - {...props} - > - {children} - </span> -); +}: DescriptionListTermHelpTextButtonProps) => { + const helpTextRef = createRef<HTMLSpanElement>(); + + const handleKeys = (event: React.KeyboardEvent<HTMLSpanElement>) => { + if (!helpTextRef.current || helpTextRef.current !== (event.target as HTMLElement)) { + return; + } + + const key = event.key; + if (key === 'Enter' || key === ' ') { + event.preventDefault(); + helpTextRef.current.click(); + } + }; + + return ( + <span + ref={helpTextRef} + className={css(className, styles.descriptionListText, styles.modifiers.helpText)} + role="button" + type="button" + tabIndex={0} + onKeyDown={(event) => handleKeys(event)} + {...props} + > + {children} + </span> + ); +}; DescriptionListTermHelpTextButton.displayName = 'DescriptionListTermHelpTextButton'; diff --git a/packages/react-core/src/components/DescriptionList/__tests__/DescriptionList.test.tsx b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionList.test.tsx index f9e8d6b01cc..7b344c1b739 100644 --- a/packages/react-core/src/components/DescriptionList/__tests__/DescriptionList.test.tsx +++ b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionList.test.tsx @@ -1,130 +1,157 @@ -import React from 'react'; -import { shallow, mount } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import { DescriptionList } from '../DescriptionList'; -import { DescriptionListGroup } from '../DescriptionListGroup'; -import { DescriptionListTerm } from '../DescriptionListTerm'; -import { DescriptionListDescription } from '../DescriptionListDescription'; -import { DescriptionListTermHelpText } from '../DescriptionListTermHelpText'; -import { DescriptionListTermHelpTextButton } from '../DescriptionListTermHelpTextButton'; - -describe('Description List', () => { - test('default', () => { - const view = shallow(<DescriptionList />); - expect(view).toMatchSnapshot(); - }); - test('1 col on all breakpoints', () => { - const view = shallow( - <DescriptionList columnModifier={{ default: '1Col', md: '1Col', lg: '1Col', xl: '1Col', '2xl': '1Col' }} /> - ); - expect(view).toMatchSnapshot(); - }); +import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; - test('2 col on all breakpoints', () => { - const view = shallow( - <DescriptionList columnModifier={{ default: '2Col', md: '2Col', lg: '2Col', xl: '2Col', '2xl': '2Col' }} /> - ); - expect(view).toMatchSnapshot(); - }); +test('Renders to match snapshot', () => { + const { asFragment } = render(<DescriptionList />); + expect(asFragment()).toMatchSnapshot(); +}); - test('3 col on all breakpoints', () => { - const view = shallow( - <DescriptionList columnModifier={{ default: '3Col', md: '3Col', lg: '3Col', xl: '3Col', '2xl': '3Col' }} /> - ); - expect(view).toMatchSnapshot(); - }); +test(`Renders default class ${styles.descriptionList}`, () => { + render(<DescriptionList aria-label="list" />); + expect(screen.getByLabelText('list')).toHaveClass(styles.descriptionList, { exact: true }); +}); - test('Horizontal Description List', () => { - const view = shallow(<DescriptionList isHorizontal />); - expect(view).toMatchSnapshot(); - }); +test('Renders custom className', () => { + render(<DescriptionList aria-label="list" className="custom" />); + expect(screen.getByLabelText('list')).toHaveClass('custom'); +}); - test('Compact Description List', () => { - const view = shallow(<DescriptionList isCompact />); - expect(view).toMatchSnapshot(); +Object.values(['1Col', '2Col', '3Col']).forEach((_col) => { + const col = _col as '1Col' | '2Col' | '3Col'; + test(`Renders ${col} on all breakpoints`, () => { + render( + <DescriptionList + aria-label="list" + columnModifier={{ default: col, sm: col, md: col, lg: col, xl: col, '2xl': col }} + /> + ); + expect(screen.getByLabelText('list')).toHaveClass( + styles.modifiers[col], + styles.modifiers[`${col}OnSm`], + styles.modifiers[`${col}OnMd`], + styles.modifiers[`${col}OnLg`], + styles.modifiers[`${col}OnXl`], + styles.modifiers[`${col}On_2xl`] + ); }); +}); - test('Compact Horizontal Description List', () => { - const view = shallow(<DescriptionList isCompact isHorizontal />); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.horizontal} when isHorizontal = true`, () => { + render(<DescriptionList aria-label="list" isHorizontal />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.horizontal); +}); - test('Fluid Horizontal Description List', () => { - const view = shallow(<DescriptionList isFluid isHorizontal />); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.compact} when isCompact = true`, () => { + render(<DescriptionList aria-label="list" isCompact />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.compact); +}); - test('alignment breakpoints', () => { - const view = mount( +test(`Renders ${styles.modifiers.horizontal} and ${styles.modifiers.fluid} when isFluid = true`, () => { + render(<DescriptionList aria-label="list" isFluid />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.fluid, styles.modifiers.horizontal); +}); + +Object.values(['horizontal', 'vertical']).forEach((_align) => { + const align = _align as 'horizontal' | 'vertical'; + test(`Renders ${align} on all breakpoints`, () => { + render( <DescriptionList - isHorizontal + aria-label="list" orientation={{ - sm: 'horizontal', - md: 'vertical', - lg: 'horizontal', - xl: 'vertical', - '2xl': 'horizontal' + sm: align, + md: align, + lg: align, + xl: align, + '2xl': align }} /> ); - expect(view).toMatchSnapshot(); + expect(screen.getByLabelText('list')).toHaveClass( + styles.modifiers[`${align}OnSm`], + styles.modifiers[`${align}OnMd`], + styles.modifiers[`${align}OnLg`], + styles.modifiers[`${align}OnXl`], + styles.modifiers[`${align}On_2xl`] + ); }); +}); - test('Auto Column Widths Description List', () => { - const view = shallow(<DescriptionList isAutoColumnWidths />); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.autoColumnWidths} when isAutoColumnWidths = true`, () => { + render(<DescriptionList aria-label="list" isAutoColumnWidths />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.autoColumnWidths); +}); - test('Inline Grid Description List', () => { - const view = shallow(<DescriptionList isInlineGrid />); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.inlineGrid} when isInlineGrid = true`, () => { + render(<DescriptionList aria-label="list" isInlineGrid />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.inlineGrid); +}); - test('Auto fit Description List', () => { - const view = shallow(<DescriptionList isAutoFit />); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.autoFit} when isAutoFit = true`, () => { + render(<DescriptionList aria-label="list" isAutoFit />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.autoFit); +}); - test('Auto fit with responsive grid Description List', () => { - const view = shallow( - <DescriptionList isAutoFit autoFitMinModifier={{ md: '100px', lg: '150px', xl: '200px', '2xl': '300px' }} /> - ); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.fillColumns} when isFillColumns = true`, () => { + render(<DescriptionList aria-label="list" isFillColumns />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.fillColumns); +}); - test('Term default', () => { - const view = shallow( - <DescriptionListTerm key="term-id-1" aria-labelledby="term-1"> - test - </DescriptionListTerm> - ); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.displayLg} when displaySize = lg`, () => { + render(<DescriptionList aria-label="list" displaySize="lg" />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.displayLg); +}); - test('Term helper text', () => { - const view = shallow( - <DescriptionListTermHelpText key="term-id-1" aria-labelledby="term-1"> - <DescriptionListTermHelpTextButton>test</DescriptionListTermHelpTextButton> - </DescriptionListTermHelpText> - ); - expect(view).toMatchSnapshot(); - }); +test(`Renders ${styles.modifiers.display_2xl} when displaySize = 2xl`, () => { + render(<DescriptionList aria-label="list" displaySize="2xl" />); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.display_2xl); +}); - test('Group', () => { - const view = shallow( - <DescriptionListGroup className="custom-description-list-group" aria-labelledby="group-1"> - test - </DescriptionListGroup> - ); - expect(view).toMatchSnapshot(); - }); +test(`Renders style when isHorizontal and horizontalTermWidthModifier is set`, () => { + render( + <DescriptionList + aria-label="list" + isHorizontal + horizontalTermWidthModifier={{ + default: '12ch', + sm: '15ch', + md: '20ch', + lg: '28ch', + xl: '30ch', + '2xl': '35ch' + }} + /> + ); + const listStyles = {}; + listStyles[`--${styles.descriptionList}--m-horizontal__term--width`] = '12ch'; + listStyles[`--${styles.descriptionList}--m-horizontal__term--width-on-sm`] = '15ch'; + listStyles[`--${styles.descriptionList}--m-horizontal__term--width-on-md`] = '20ch'; + listStyles[`--${styles.descriptionList}--m-horizontal__term--width-on-lg`] = '28ch'; + listStyles[`--${styles.descriptionList}--m-horizontal__term--width-on-xl`] = '30ch'; + listStyles[`--${styles.descriptionList}--m-horizontal__term--width-on-2xl`] = '35ch'; + expect(screen.getByLabelText('list')).toHaveStyle(listStyles); +}); - test('Description', () => { - const view = shallow( - <DescriptionListDescription className="custom-description-list-description" aria-labelledby="description-1"> - test - </DescriptionListDescription> - ); - expect(view).toMatchSnapshot(); - }); +test(`Renders style when termWidth is set`, () => { + render(<DescriptionList aria-label="list" isHorizontal termWidth="30px" />); + const listStyles = {}; + listStyles[`--${styles.descriptionList}__term--width`] = '30px'; + expect(screen.getByLabelText('list')).toHaveStyle(listStyles); +}); + +test(`Renders style when isAutoFit and horizontalTermWidthModifier is set`, () => { + render( + <DescriptionList + aria-label="list" + isAutoFit + autoFitMinModifier={{ default: '50px', sm: '50px', md: '100px', lg: '150px', xl: '200px', '2xl': '300px' }} + /> + ); + const listStyles = {}; + + expect(screen.getByLabelText('list')).toHaveAttribute( + 'style', + `--${styles.descriptionList}--GridTemplateColumns--min: 50px; --${styles.descriptionList}--GridTemplateColumns--min-on-sm: 50px; --${styles.descriptionList}--GridTemplateColumns--min-on-md: 100px; --${styles.descriptionList}--GridTemplateColumns--min-on-lg: 150px; --${styles.descriptionList}--GridTemplateColumns--min-on-xl: 200px; --${styles.descriptionList}--GridTemplateColumns--min-on-2xl: 300px;` + ); }); diff --git a/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListDescription.test.tsx b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListDescription.test.tsx new file mode 100644 index 00000000000..e18009a2604 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListDescription.test.tsx @@ -0,0 +1,24 @@ +import { render, screen } from '@testing-library/react'; +import { DescriptionListDescription } from '../DescriptionListDescription'; + +import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render(<DescriptionListDescription>test</DescriptionListDescription>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders default class ${styles.descriptionListDescription}`, () => { + render(<DescriptionListDescription>test</DescriptionListDescription>); + expect(screen.getByText('test').parentElement).toHaveClass(styles.descriptionListDescription, { exact: true }); +}); + +test('Renders custom className', () => { + render(<DescriptionListDescription className="custom">test</DescriptionListDescription>); + expect(screen.getByText('test').parentElement).toHaveClass('custom'); +}); + +test('Renders spread props', () => { + render(<DescriptionListDescription id="id">test</DescriptionListDescription>); + expect(screen.getByText('test').parentElement).toHaveAttribute('id', 'id'); +}); diff --git a/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListGroup.test.tsx b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListGroup.test.tsx new file mode 100644 index 00000000000..18e07ca68b9 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListGroup.test.tsx @@ -0,0 +1,24 @@ +import { render, screen } from '@testing-library/react'; +import { DescriptionListGroup } from '../DescriptionListGroup'; + +import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render(<DescriptionListGroup>test</DescriptionListGroup>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders default class ${styles.descriptionListGroup}`, () => { + render(<DescriptionListGroup>test</DescriptionListGroup>); + expect(screen.getByText('test')).toHaveClass(styles.descriptionListGroup, { exact: true }); +}); + +test('Renders custom className', () => { + render(<DescriptionListGroup className="custom">test</DescriptionListGroup>); + expect(screen.getByText('test')).toHaveClass('custom'); +}); + +test('Renders spread props', () => { + render(<DescriptionListGroup id="id">test</DescriptionListGroup>); + expect(screen.getByText('test')).toHaveAttribute('id', 'id'); +}); diff --git a/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListHelpTextButton.test.tsx b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListHelpTextButton.test.tsx new file mode 100644 index 00000000000..120279c6fda --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListHelpTextButton.test.tsx @@ -0,0 +1,26 @@ +import { render, screen } from '@testing-library/react'; +import { DescriptionListTermHelpTextButton } from '../DescriptionListTermHelpTextButton'; + +import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render(<DescriptionListTermHelpTextButton>test</DescriptionListTermHelpTextButton>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders default class ${styles.descriptionListText}`, () => { + render(<DescriptionListTermHelpTextButton>test</DescriptionListTermHelpTextButton>); + expect(screen.getByText('test')).toHaveClass(`${styles.descriptionListText} ${styles.modifiers.helpText}`, { + exact: true + }); +}); + +test('Renders custom className', () => { + render(<DescriptionListTermHelpTextButton className="custom">test</DescriptionListTermHelpTextButton>); + expect(screen.getByText('test')).toHaveClass('custom'); +}); + +test('Renders spread props', () => { + render(<DescriptionListTermHelpTextButton id="id">test</DescriptionListTermHelpTextButton>); + expect(screen.getByText('test')).toHaveAttribute('id', 'id'); +}); diff --git a/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListTerm.test.tsx b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListTerm.test.tsx new file mode 100644 index 00000000000..173ba1bf4c0 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListTerm.test.tsx @@ -0,0 +1,34 @@ +import { render, screen } from '@testing-library/react'; +import { DescriptionListTerm } from '../DescriptionListTerm'; + +import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render(<DescriptionListTerm>test</DescriptionListTerm>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders default class ${styles.descriptionListTerm}`, () => { + render(<DescriptionListTerm>test</DescriptionListTerm>); + expect(screen.getByText('test').parentElement).toHaveClass(styles.descriptionListTerm, { exact: true }); +}); + +test(`Renders default class ${styles.descriptionListText}`, () => { + render(<DescriptionListTerm>test</DescriptionListTerm>); + expect(screen.getByText('test')).toHaveClass(styles.descriptionListText, { exact: true }); +}); + +test('Renders custom className', () => { + render(<DescriptionListTerm className="custom">test</DescriptionListTerm>); + expect(screen.getByText('test').parentElement).toHaveClass('custom'); +}); + +test('Renders icon', () => { + render(<DescriptionListTerm icon={<div>icon</div>}>test</DescriptionListTerm>); + expect(screen.getByText('icon').parentElement).toHaveClass(styles.descriptionListTermIcon); +}); + +test('Renders spread props', () => { + render(<DescriptionListTerm id="id">test</DescriptionListTerm>); + expect(screen.getByText('test').parentElement).toHaveAttribute('id', 'id'); +}); diff --git a/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListTermHelpText.test.tsx b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListTermHelpText.test.tsx new file mode 100644 index 00000000000..27acbaf3d93 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/DescriptionListTermHelpText.test.tsx @@ -0,0 +1,24 @@ +import { render, screen } from '@testing-library/react'; +import { DescriptionListTermHelpText } from '../DescriptionListTermHelpText'; + +import styles from '@patternfly/react-styles/css/components/DescriptionList/description-list'; + +test('Renders to match snapshot', () => { + const { asFragment } = render(<DescriptionListTermHelpText>test</DescriptionListTermHelpText>); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Renders default class ${styles.descriptionListTerm}`, () => { + render(<DescriptionListTermHelpText>test</DescriptionListTermHelpText>); + expect(screen.getByText('test')).toHaveClass(styles.descriptionListTerm, { exact: true }); +}); + +test('Renders custom className', () => { + render(<DescriptionListTermHelpText className="custom">test</DescriptionListTermHelpText>); + expect(screen.getByText('test')).toHaveClass('custom'); +}); + +test('Renders spread props', () => { + render(<DescriptionListTermHelpText id="id">test</DescriptionListTermHelpText>); + expect(screen.getByText('test')).toHaveAttribute('id', 'id'); +}); diff --git a/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionList.test.tsx.snap b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionList.test.tsx.snap index 958efc49818..9526a9d995f 100644 --- a/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionList.test.tsx.snap +++ b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionList.test.tsx.snap @@ -1,146 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Description List 1 col on all breakpoints 1`] = ` -<dl - className="pf-c-description-list pf-m-1-col pf-m-1-col-on-md pf-m-1-col-on-lg pf-m-1-col-on-xl pf-m-1-col-on-2xl" -/> -`; - -exports[`Description List 2 col on all breakpoints 1`] = ` -<dl - className="pf-c-description-list pf-m-2-col pf-m-2-col-on-md pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-2-col-on-2xl" -/> -`; - -exports[`Description List 3 col on all breakpoints 1`] = ` -<dl - className="pf-c-description-list pf-m-3-col pf-m-3-col-on-md pf-m-3-col-on-lg pf-m-3-col-on-xl pf-m-3-col-on-2xl" -/> -`; - -exports[`Description List Auto Column Widths Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-auto-column-widths" -/> -`; - -exports[`Description List Auto fit Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-auto-fit" -/> -`; - -exports[`Description List Auto fit with responsive grid Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-auto-fit" - style={ - Object { - "--pf-c-description-list--GridTemplateColumns--min-on-2xl": "300px", - "--pf-c-description-list--GridTemplateColumns--min-on-lg": "150px", - "--pf-c-description-list--GridTemplateColumns--min-on-md": "100px", - "--pf-c-description-list--GridTemplateColumns--min-on-xl": "200px", - } - } -/> -`; - -exports[`Description List Compact Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-compact" -/> -`; - -exports[`Description List Compact Horizontal Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-horizontal pf-m-compact" -/> -`; - -exports[`Description List Description 1`] = ` -<dd - aria-labelledby="description-1" - className="pf-c-description-list__description custom-description-list-description" -> - <div - className="pf-c-description-list__text" - > - test - </div> -</dd> -`; - -exports[`Description List Fluid Horizontal Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-horizontal pf-m-fluid" -/> -`; - -exports[`Description List Group 1`] = ` -<div - aria-labelledby="group-1" - className="pf-c-description-list__group custom-description-list-group" -> - test -</div> -`; - -exports[`Description List Horizontal Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-horizontal" -/> -`; - -exports[`Description List Inline Grid Description List 1`] = ` -<dl - className="pf-c-description-list pf-m-inline-grid" -/> -`; - -exports[`Description List Term default 1`] = ` -<dt - aria-labelledby="term-1" - className="pf-c-description-list__term" -> - <span - className="pf-c-description-list__text" - > - test - </span> -</dt> -`; - -exports[`Description List Term helper text 1`] = ` -<dt - aria-labelledby="term-1" - className="pf-c-description-list__term" -> - <DescriptionListTermHelpTextButton> - test - </DescriptionListTermHelpTextButton> -</dt> -`; - -exports[`Description List alignment breakpoints 1`] = ` -<DescriptionList - isHorizontal={true} - orientation={ - Object { - "2xl": "horizontal", - "lg": "horizontal", - "md": "vertical", - "sm": "horizontal", - "xl": "vertical", - } - } -> +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> <dl - className="pf-c-description-list pf-m-horizontal pf-m-horizontal-on-sm pf-m-vertical-on-md pf-m-horizontal-on-lg pf-m-vertical-on-xl pf-m-horizontal-on-2xl" + class="pf-v6-c-description-list" /> -</DescriptionList> -`; - -exports[`Description List default 1`] = ` -<dl - className="pf-c-description-list" -/> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListDescription.test.tsx.snap b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListDescription.test.tsx.snap new file mode 100644 index 00000000000..a476abc789c --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListDescription.test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <dd + class="pf-v6-c-description-list__description" + > + <div + class="pf-v6-c-description-list__text" + > + test + </div> + </dd> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListGroup.test.tsx.snap b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListGroup.test.tsx.snap new file mode 100644 index 00000000000..6c8106864e6 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListGroup.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-description-list__group" + > + test + </div> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListHelpTextButton.test.tsx.snap b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListHelpTextButton.test.tsx.snap new file mode 100644 index 00000000000..a34f87dcf70 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListHelpTextButton.test.tsx.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <span + class="pf-v6-c-description-list__text pf-m-help-text" + role="button" + tabindex="0" + type="button" + > + test + </span> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListTerm.test.tsx.snap b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListTerm.test.tsx.snap new file mode 100644 index 00000000000..4c66eb30ec8 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListTerm.test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <dt + class="pf-v6-c-description-list__term" + > + <span + class="pf-v6-c-description-list__text" + > + test + </span> + </dt> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListTermHelpText.test.tsx.snap b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListTermHelpText.test.tsx.snap new file mode 100644 index 00000000000..f151b5e9d7c --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/__tests__/__snapshots__/DescriptionListTermHelpText.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Renders to match snapshot 1`] = ` +<DocumentFragment> + <dt + class="pf-v6-c-description-list__term" + > + test + </dt> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionList.md b/packages/react-core/src/components/DescriptionList/examples/DescriptionList.md index 469337c20f4..aab85cf2a00 100644 --- a/packages/react-core/src/components/DescriptionList/examples/DescriptionList.md +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionList.md @@ -1,7 +1,7 @@ --- id: 'Description list' section: components -cssPrefix: 'pf-c-description-list' +cssPrefix: 'pf-v6-c-description-list' propComponents: [ 'DescriptionList', @@ -11,929 +11,166 @@ propComponents: 'DescriptionListTermHelpText', 'DescriptionListTermHelpTextButton', 'Popover', + 'Card' ] --- -import { Button, DescriptionList, DescriptionListTerm, DescriptionListDescription, DescriptionListGroup, DescriptionListTermHelpText, DescriptionListTermHelpTextButton, Popover } from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; +import { useState } from 'react'; +import { Button, DescriptionList, DescriptionListTerm, DescriptionListDescription, DescriptionListGroup, DescriptionListTermHelpText, DescriptionListTermHelpTextButton, Popover, Checkbox, Card } from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; +import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon'; +import BookIcon from '@patternfly/react-icons/dist/esm/icons/book-icon'; +import KeyIcon from '@patternfly/react-icons/dist/esm/icons/key-icon'; +import GlobeIcon from '@patternfly/react-icons/dist/esm/icons/globe-icon'; +import FlagIcon from '@patternfly/react-icons/dist/esm/icons/flag-icon'; ## Examples ### Basic -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListBasic.tsx' ``` ### Term help text -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListGroup, - DescriptionListDescription, - DescriptionListTermHelpText, - DescriptionListTermHelpTextButton, - Popover -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList> - <DescriptionListGroup> - <DescriptionListTermHelpText> - <Popover headerContent={<div>Name</div>} bodyContent={<div>Additional name info</div>}> - <DescriptionListTermHelpTextButton> Name </DescriptionListTermHelpTextButton> - </Popover> - </DescriptionListTermHelpText> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTermHelpText> - <Popover headerContent={<div>Namespace</div>} bodyContent={<div>Additional namespace info</div>}> - <DescriptionListTermHelpTextButton> Namespace </DescriptionListTermHelpTextButton> - </Popover> - </DescriptionListTermHelpText> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTermHelpText> - <Popover headerContent={<div>Labels</div>} bodyContent={<div>Additional labels info</div>}> - <DescriptionListTermHelpTextButton> Labels </DescriptionListTermHelpTextButton> - </Popover> - </DescriptionListTermHelpText> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTermHelpText> - <Popover headerContent={<div>Pod selector</div>} bodyContent={<div>Additional pod selector info</div>}> - <DescriptionListTermHelpTextButton> Pod selector </DescriptionListTermHelpTextButton> - </Popover> - </DescriptionListTermHelpText> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTermHelpText> - <Popover headerContent={<div>Annotation</div>} bodyContent={<div>Additional annotation info</div>}> - <DescriptionListTermHelpTextButton> Annotation </DescriptionListTermHelpTextButton> - </Popover> - </DescriptionListTermHelpText> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListWithTermHelpText.tsx' ``` ### Default 2 col -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList - columnModifier={{ - default: '2Col' - }} -> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListDefaultTwoCol.tsx' ``` ### Default 3 col on lg -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList columnModifier={{ lg: '3Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListDefaultThreeColLg.tsx' ``` ### Horizontal -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isHorizontal> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListHorizontal.tsx' +``` + +### Horizontal using custom term width modifier + +```ts file='./DescriptionListHorizontalCustomTermWidth.tsx' ``` ### Horizontal 2 col -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isHorizontal columnModifier={{ default: '2Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListHorizontalTwoCol.tsx' ``` ### Horizontal 3 col on lg -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isHorizontal columnModifier={{ lg: '3Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListHorizontalThreeColLg.tsx' ``` ### Compact -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isCompact> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListCompact.tsx' ``` ### Compact horizontal -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isCompact isHorizontal> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListCompactHorizontal.tsx' ``` ### Fluid horizontal -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isHorizontal isFluid> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListFluidHorizontal.tsx' ``` ### Column fill -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isFillColumns columnModifier={{ default: '2Col', lg: '3Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription> - This is a long description that should wrap to multiple lines in a multi-column layout. - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListColumnFill.tsx' +``` + +### Large display size + +```ts file='./DescriptionListWithLargeDisplaySize.tsx' ``` ## Responsive column definitions ### Default responsive columns -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList columnModifier={{ lg: '2Col', xl: '3Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListDefaultResponsiveColumns.tsx' ``` ### Horizontal responsive columns -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isHorizontal columnModifier={{ lg: '2Col', xl: '3Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListHorizontalResponsiveColumns.tsx' ``` ### Responsive horizontal, vertical group layout -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList - isHorizontal - orientation={{ - md: 'vertical', - lg: 'horizontal', - xl: 'vertical', - '2xl': 'horizontal' - }} -> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListResponsiveHoriVertGroup.tsx' ``` ## Auto-column-width ### Default auto column width -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isAutoColumnWidths columnModifier={{ default: '3Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListDefaultAutoColumn.tsx' ``` ### Horizontal auto column width -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isHorizontal isAutoColumnWidths columnModifier={{ lg: '2Col' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListHorizontalAutoColumn.tsx' ``` ## Inline grid ### Default inline grid -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList columnModifier={{ default: '3Col' }} isInlineGrid> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>Example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListDefaultInlineGrid.tsx' +``` + +## Card variants + +A [card component](/components/card) can be used in place of a description list group. + +### Description list with card + +```ts file='./DescriptionListWithCard.tsx' +``` + +### Description list with large display size and card + +```ts file='./DescriptionListWithLargeDisplaySizeAndCard.tsx' +``` + +### Display size with card, three column on large breakpoint + +```ts file='./DescriptionListDisplaySizeAndCardThreeColumn.tsx' +``` + +### Display size with card, horizontal, modified term width + +```ts file='./DescriptionListDisplaySizeAndCardHorizontalTermWidth.tsx' ``` ## Auto fit ### Auto-fit basic -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isAutoFit> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListAutoFitBasic.tsx' ``` ### Auto-fit, min width modified grid template columns -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isAutoFit autoFitMinModifier={{ default: '200px' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListAutoFitMinWidthModified.tsx' ``` ### Auto-fit, min width modified, responsive grid template columns -```js -import React from 'react'; -import { - Button, - DescriptionList, - DescriptionListTerm, - DescriptionListText, - DescriptionListGroup, - DescriptionListDescription -} from '@patternfly/react-core'; -import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; - -<DescriptionList isAutoFit autoFitMinModifier={{ md: '100px', lg: '150px', xl: '200px', '2xl': '300px' }}> - <DescriptionListGroup> - <DescriptionListTerm>Name</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Namespace</DescriptionListTerm> - <DescriptionListDescription> - <a href="#">mary-test</a> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Labels</DescriptionListTerm> - <DescriptionListDescription>example</DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Pod selector</DescriptionListTerm> - <DescriptionListDescription> - <Button variant="link" isInline icon={<PlusCircleIcon />}> - app=MyApp - </Button> - </DescriptionListDescription> - </DescriptionListGroup> - <DescriptionListGroup> - <DescriptionListTerm>Annotation</DescriptionListTerm> - <DescriptionListDescription>2 Annotations</DescriptionListDescription> - </DescriptionListGroup> -</DescriptionList>; +```ts file='./DescriptionListAutoFitMinWidthResponsive.tsx' +``` + +## With icons + +### Icons on terms + +```ts file='./DescriptionListIconsOnTerms.tsx' ``` diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitBasic.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitBasic.tsx new file mode 100644 index 00000000000..bfd0fda2a9b --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitBasic.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListAutoFitBasic: React.FunctionComponent = () => ( + <DescriptionList isAutoFit aria-label="Basic auto-fit"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitMinWidthModified.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitMinWidthModified.tsx new file mode 100644 index 00000000000..d5d975f0594 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitMinWidthModified.tsx @@ -0,0 +1,43 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListAutoFitMinWidthModified: React.FunctionComponent = () => ( + <DescriptionList + isAutoFit + autoFitMinModifier={{ default: '200px' }} + aria-label="Auto-fit grid with minimum width modification" + > + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitMinWidthResponsive.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitMinWidthResponsive.tsx new file mode 100644 index 00000000000..90102a75d18 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListAutoFitMinWidthResponsive.tsx @@ -0,0 +1,43 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListAutoFitMinWidthResponsive: React.FunctionComponent = () => ( + <DescriptionList + isAutoFit + autoFitMinModifier={{ md: '100px', lg: '150px', xl: '200px', '2xl': '300px' }} + aria-label="Responsive auto-fit grid with minimum width" + > + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListBasic.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListBasic.tsx new file mode 100644 index 00000000000..a23519f6478 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListBasic.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListBasic: React.FunctionComponent = () => ( + <DescriptionList aria-label="Basic example"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListColumnFill.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListColumnFill.tsx new file mode 100644 index 00000000000..041942713d2 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListColumnFill.tsx @@ -0,0 +1,41 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListColumnFill: React.FunctionComponent = () => ( + <DescriptionList isFillColumns columnModifier={{ default: '2Col', lg: '3Col' }} aria-label="Column fill enabled"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription> + This is a long description that should wrap to multiple lines in a multi-column layout. + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListCompact.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListCompact.tsx new file mode 100644 index 00000000000..dcd0a6a1d45 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListCompact.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListCompact: React.FunctionComponent = () => ( + <DescriptionList isCompact aria-label="Compact example"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListCompactHorizontal.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListCompactHorizontal.tsx new file mode 100644 index 00000000000..7d2781b1dc4 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListCompactHorizontal.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListCompactHorizontal: React.FunctionComponent = () => ( + <DescriptionList isCompact isHorizontal aria-label="Compact horizontal"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultAutoColumn.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultAutoColumn.tsx new file mode 100644 index 00000000000..f9ccbdd4366 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultAutoColumn.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListDefaultAutoColumn: React.FunctionComponent = () => ( + <DescriptionList isAutoColumnWidths columnModifier={{ default: '3Col' }} aria-label="Default auto column width"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultInlineGrid.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultInlineGrid.tsx new file mode 100644 index 00000000000..463a7abd294 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultInlineGrid.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListDefaultInlineGrid: React.FunctionComponent = () => ( + <DescriptionList columnModifier={{ default: '3Col' }} isInlineGrid aria-label="Default inline grid"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultResponsiveColumns.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultResponsiveColumns.tsx new file mode 100644 index 00000000000..6c6060a734a --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultResponsiveColumns.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListDefaultResponsiveColumns: React.FunctionComponent = () => ( + <DescriptionList columnModifier={{ lg: '2Col', xl: '3Col' }} aria-label="Default responsive columns"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultThreeColLg.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultThreeColLg.tsx new file mode 100644 index 00000000000..13cfdded80f --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultThreeColLg.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListDefaultThreeColLg: React.FunctionComponent = () => ( + <DescriptionList columnModifier={{ lg: '3Col' }} aria-label="Three-column on large screens"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultTwoCol.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultTwoCol.tsx new file mode 100644 index 00000000000..cc57b073d37 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDefaultTwoCol.tsx @@ -0,0 +1,44 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListDefaultTwoCol: React.FunctionComponent = () => ( + <DescriptionList + columnModifier={{ + default: '2Col' + }} + aria-label="Two-column" + > + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListDisplaySizeAndCardHorizontalTermWidth.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDisplaySizeAndCardHorizontalTermWidth.tsx new file mode 100644 index 00000000000..eedfa6ad336 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDisplaySizeAndCardHorizontalTermWidth.tsx @@ -0,0 +1,39 @@ +import { Button, DescriptionList, DescriptionListTerm, DescriptionListDescription, Card } from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListDisplaySizeAndCardHorizontalTermWidth: React.FunctionComponent = () => ( + <DescriptionList + displaySize="lg" + isHorizontal + columnModifier={{ lg: '2Col' }} + termWidth="10ch" + aria-label="Display size with card, horizontal and modified term width" + > + <Card component="div"> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </Card> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListDisplaySizeAndCardThreeColumn.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDisplaySizeAndCardThreeColumn.tsx new file mode 100644 index 00000000000..da2685ff06b --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListDisplaySizeAndCardThreeColumn.tsx @@ -0,0 +1,37 @@ +import { Button, DescriptionList, DescriptionListTerm, DescriptionListDescription, Card } from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListDisplayLgAndCardThreeColumn: React.FunctionComponent = () => ( + <DescriptionList + displaySize="lg" + columnModifier={{ lg: '3Col' }} + aria-label="Display size with card and three column on large breakpoint" + > + <Card component="div"> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </Card> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListFluidHorizontal.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListFluidHorizontal.tsx new file mode 100644 index 00000000000..e3e6c97325c --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListFluidHorizontal.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListFluidHorizontal: React.FunctionComponent = () => ( + <DescriptionList isHorizontal isFluid aria-label="Fluid horizontal"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontal.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontal.tsx new file mode 100644 index 00000000000..c36d0170b2b --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontal.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListHorizontal: React.FunctionComponent = () => ( + <DescriptionList isHorizontal aria-label="Horizontal"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalAutoColumn.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalAutoColumn.tsx new file mode 100644 index 00000000000..12699d16a82 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalAutoColumn.tsx @@ -0,0 +1,44 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListHorizontalAutoColumn: React.FunctionComponent = () => ( + <DescriptionList + isHorizontal + isAutoColumnWidths + columnModifier={{ lg: '2Col' }} + aria-label="Horizontal auto column width" + > + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalCustomTermWidth.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalCustomTermWidth.tsx new file mode 100644 index 00000000000..e3308dd6d59 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalCustomTermWidth.tsx @@ -0,0 +1,50 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListHorizontalCustomTermWidth: React.FunctionComponent = () => ( + <DescriptionList + isHorizontal + horizontalTermWidthModifier={{ + default: '12ch', + sm: '15ch', + md: '20ch', + lg: '28ch', + xl: '30ch', + '2xl': '35ch' + }} + aria-label="Horizontal with custom term width modifier" + > + <DescriptionListGroup> + <DescriptionListTerm>Name longer than the default term width</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalResponsiveColumns.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalResponsiveColumns.tsx new file mode 100644 index 00000000000..be578e313a3 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalResponsiveColumns.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListHorizontalResponsiveColumns: React.FunctionComponent = () => ( + <DescriptionList isHorizontal columnModifier={{ lg: '2Col', xl: '3Col' }} aria-label="Horizontal responsive columns"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalThreeColLg.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalThreeColLg.tsx new file mode 100644 index 00000000000..20a6585dcab --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalThreeColLg.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListHorizontalThreeColLg: React.FunctionComponent = () => ( + <DescriptionList isHorizontal columnModifier={{ lg: '3Col' }} aria-label="Three-columns horizontal on large screens"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalTwoCol.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalTwoCol.tsx new file mode 100644 index 00000000000..9276f1002c0 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListHorizontalTwoCol.tsx @@ -0,0 +1,39 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListHorizontalTwoCol: React.FunctionComponent = () => ( + <DescriptionList isHorizontal columnModifier={{ default: '2Col' }} aria-label="Two-column horizontal"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListIconsOnTerms.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListIconsOnTerms.tsx new file mode 100644 index 00000000000..f74270cd00e --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListIconsOnTerms.tsx @@ -0,0 +1,44 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; +import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon'; +import BookIcon from '@patternfly/react-icons/dist/esm/icons/book-icon'; +import KeyIcon from '@patternfly/react-icons/dist/esm/icons/key-icon'; +import GlobeIcon from '@patternfly/react-icons/dist/esm/icons/globe-icon'; +import FlagIcon from '@patternfly/react-icons/dist/esm/icons/flag-icon'; + +export const DescriptionListIconsOnTerms: React.FunctionComponent = () => ( + <DescriptionList aria-label="With icons examples"> + <DescriptionListGroup> + <DescriptionListTerm icon={<CubeIcon />}>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm icon={<BookIcon />}>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm icon={<KeyIcon />}>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm icon={<GlobeIcon />}>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm icon={<FlagIcon />}>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListResponsiveHoriVertGroup.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListResponsiveHoriVertGroup.tsx new file mode 100644 index 00000000000..a57caab2179 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListResponsiveHoriVertGroup.tsx @@ -0,0 +1,48 @@ +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListResponsiveHoriVertGroup: React.FunctionComponent = () => ( + <DescriptionList + isHorizontal + orientation={{ + md: 'vertical', + lg: 'horizontal', + xl: 'vertical', + '2xl': 'horizontal' + }} + aria-label="Responsive orientation" + > + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithCard.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithCard.tsx new file mode 100644 index 00000000000..57bba6e38ad --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithCard.tsx @@ -0,0 +1,62 @@ +import { useState } from 'react'; +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListDescription, + Card, + Checkbox +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListWithCard: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState<boolean>(false); + const [isSelectable, setSelectable] = useState<boolean>(false); + + const toggleSelectable = (checked: boolean) => { + setSelectable(checked ? true : false); + setIsChecked(checked); + }; + return ( + <> + <div style={{ marginBottom: '12px' }}> + <Checkbox + label="isSelectable" + isChecked={isChecked} + onChange={(_event, checked) => toggleSelectable(checked)} + aria-label="set isSelectable" + id="toggle-isSelectable" + name="toggle-isSelectable" + /> + </div> + <DescriptionList columnModifier={{ lg: '2Col' }} aria-label="With card example"> + <Card component="div" isSelectable={isSelectable}> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </Card> + <Card component="div" isSelectable={isSelectable}> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </Card> + <Card component="div" isSelectable={isSelectable}> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </Card> + <Card component="div" isSelectable={isSelectable}> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </Card> + <Card component="div" isSelectable={isSelectable}> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </Card> + </DescriptionList> + </> + ); +}; diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithLargeDisplaySize.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithLargeDisplaySize.tsx new file mode 100644 index 00000000000..2c36dfa4adb --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithLargeDisplaySize.tsx @@ -0,0 +1,63 @@ +import { useState } from 'react'; +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListGroup, + DescriptionListDescription, + Checkbox +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListWithLargeDisplaySize: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState<boolean>(false); + const [displaySize, setDisplaySize] = useState<'lg' | '2xl'>('lg'); + + const toggleDisplaySize = (checked: boolean) => { + setDisplaySize(checked ? '2xl' : 'lg'); + setIsChecked(checked); + }; + + return ( + <> + <div style={{ marginBottom: '12px' }}> + <Checkbox + label="displaySize 2xl" + isChecked={isChecked} + onChange={(_event, checked) => toggleDisplaySize(checked)} + aria-label="set display size 2xl" + id="toggle-display-size" + name="toggle-display-size" + /> + </div> + <DescriptionList displaySize={displaySize} columnModifier={{ lg: '2Col' }} aria-label="Large display size"> + <DescriptionListGroup> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> + </> + ); +}; diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithLargeDisplaySizeAndCard.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithLargeDisplaySizeAndCard.tsx new file mode 100644 index 00000000000..2a25a652870 --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithLargeDisplaySizeAndCard.tsx @@ -0,0 +1,67 @@ +import { useState } from 'react'; +import { + Button, + DescriptionList, + DescriptionListTerm, + DescriptionListDescription, + Card, + Checkbox +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListWithLargeDisplaySizeAndCard: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = useState<boolean>(false); + const [displaySize, setDisplaySize] = useState<'lg' | '2xl'>('lg'); + + const toggleDisplaySize = (checked: boolean) => { + setDisplaySize(checked ? '2xl' : 'lg'); + setIsChecked(checked); + }; + + return ( + <> + <div style={{ marginBottom: '12px' }}> + <Checkbox + label="displaySize 2xl" + isChecked={isChecked} + onChange={(_event, checked) => toggleDisplaySize(checked)} + aria-label="set display size 2xl" + id="toggle-display-size-with-card" + name="toggle-display-size-with-card" + /> + </div> + <DescriptionList + displaySize={displaySize} + columnModifier={{ lg: '2Col' }} + aria-label="With large display size and card" + > + <Card component="div"> + <DescriptionListTerm>Name</DescriptionListTerm> + <DescriptionListDescription>Example</DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Namespace</DescriptionListTerm> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Labels</DescriptionListTerm> + <DescriptionListDescription>example</DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Pod selector</DescriptionListTerm> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </Card> + <Card component="div"> + <DescriptionListTerm>Annotation</DescriptionListTerm> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </Card> + </DescriptionList> + </> + ); +}; diff --git a/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithTermHelpText.tsx b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithTermHelpText.tsx new file mode 100644 index 00000000000..a5e8c1f7f1a --- /dev/null +++ b/packages/react-core/src/components/DescriptionList/examples/DescriptionListWithTermHelpText.tsx @@ -0,0 +1,61 @@ +import { + Button, + DescriptionList, + DescriptionListGroup, + DescriptionListDescription, + DescriptionListTermHelpText, + DescriptionListTermHelpTextButton, + Popover +} from '@patternfly/react-core'; +import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon'; + +export const DescriptionListWithTermHelpText: React.FunctionComponent = () => ( + <DescriptionList aria-label="Term help text"> + <DescriptionListGroup> + <DescriptionListTermHelpText> + <Popover headerContent={<div>Name</div>} bodyContent={<div>Additional name info</div>}> + <DescriptionListTermHelpTextButton> Name </DescriptionListTermHelpTextButton> + </Popover> + </DescriptionListTermHelpText> + <DescriptionListDescription>Example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTermHelpText> + <Popover headerContent={<div>Namespace</div>} bodyContent={<div>Additional namespace info</div>}> + <DescriptionListTermHelpTextButton> Namespace </DescriptionListTermHelpTextButton> + </Popover> + </DescriptionListTermHelpText> + <DescriptionListDescription> + <a href="#">mary-test</a> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTermHelpText> + <Popover headerContent={<div>Labels</div>} bodyContent={<div>Additional labels info</div>}> + <DescriptionListTermHelpTextButton> Labels </DescriptionListTermHelpTextButton> + </Popover> + </DescriptionListTermHelpText> + <DescriptionListDescription>example</DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTermHelpText> + <Popover headerContent={<div>Pod selector</div>} bodyContent={<div>Additional pod selector info</div>}> + <DescriptionListTermHelpTextButton> Pod selector </DescriptionListTermHelpTextButton> + </Popover> + </DescriptionListTermHelpText> + <DescriptionListDescription> + <Button variant="link" isInline icon={<RhUiAddCircleFillIcon />}> + app=MyApp + </Button> + </DescriptionListDescription> + </DescriptionListGroup> + <DescriptionListGroup> + <DescriptionListTermHelpText> + <Popover headerContent={<div>Annotation</div>} bodyContent={<div>Additional annotation info</div>}> + <DescriptionListTermHelpTextButton> Annotation </DescriptionListTermHelpTextButton> + </Popover> + </DescriptionListTermHelpText> + <DescriptionListDescription>2 Annotations</DescriptionListDescription> + </DescriptionListGroup> + </DescriptionList> +); diff --git a/packages/react-core/src/components/Divider/Divider.tsx b/packages/react-core/src/components/Divider/Divider.tsx index 321f5190835..ed5ac8342be 100644 --- a/packages/react-core/src/components/Divider/Divider.tsx +++ b/packages/react-core/src/components/Divider/Divider.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Divider/divider'; import { formatBreakpointMods } from '../../helpers/util'; @@ -14,8 +13,6 @@ export interface DividerProps extends React.HTMLProps<HTMLElement> { className?: string; /** The component type to use */ component?: 'hr' | 'li' | 'div'; - /** Flag to indicate the divider is vertical (must be in a flex layout) */ - isVertical?: boolean; /** Insets at various breakpoints. */ inset?: { default?: 'insetNone' | 'insetXs' | 'insetSm' | 'insetMd' | 'insetLg' | 'insetXl' | 'inset2xl' | 'inset3xl'; @@ -25,13 +22,25 @@ export interface DividerProps extends React.HTMLProps<HTMLElement> { xl?: 'insetNone' | 'insetXs' | 'insetSm' | 'insetMd' | 'insetLg' | 'insetXl' | 'inset2xl' | 'inset3xl'; '2xl'?: 'insetNone' | 'insetXs' | 'insetSm' | 'insetMd' | 'insetLg' | 'insetXl' | 'inset2xl' | 'inset3xl'; }; + /** Indicates how the divider will display at various breakpoints. Vertical divider must be in a flex layout. */ + orientation?: { + default?: 'vertical' | 'horizontal'; + sm?: 'vertical' | 'horizontal'; + md?: 'vertical' | 'horizontal'; + lg?: 'vertical' | 'horizontal'; + xl?: 'vertical' | 'horizontal'; + '2xl'?: 'vertical' | 'horizontal'; + }; + /** The ARIA role of the divider when the component property has a value other than "hr". */ + role?: 'separator' | 'presentation'; } export const Divider: React.FunctionComponent<DividerProps> = ({ className, component = DividerVariant.hr, - isVertical = false, inset, + orientation, + role = 'separator', ...props }: DividerProps) => { const Component: any = component; @@ -40,11 +49,11 @@ export const Divider: React.FunctionComponent<DividerProps> = ({ <Component className={css( styles.divider, - isVertical && styles.modifiers.vertical, formatBreakpointMods(inset, styles), + formatBreakpointMods(orientation, styles), className )} - {...(component !== 'hr' && { role: 'separator' })} + {...(component !== 'hr' && { role })} {...props} /> ); diff --git a/packages/react-core/src/components/Divider/__tests__/Divider.test.tsx b/packages/react-core/src/components/Divider/__tests__/Divider.test.tsx index f9e94d18833..f6a7dbb3c99 100644 --- a/packages/react-core/src/components/Divider/__tests__/Divider.test.tsx +++ b/packages/react-core/src/components/Divider/__tests__/Divider.test.tsx @@ -1,30 +1,107 @@ +import { render, screen } from '@testing-library/react'; import { Divider } from '../Divider'; -import { Flex, FlexItem} from '../../../layouts/Flex'; -import * as React from 'react'; -import { shallow } from 'enzyme'; +import styles from '@patternfly/react-styles/css/components/Divider/divider'; -test('divider using hr', () => { - const view = shallow(<Divider />); - expect(view).toMatchSnapshot(); +test(`Renders with only the class name ${styles.divider} by default`, () => { + render(<Divider />); + expect(screen.getByRole('separator')).toHaveClass(styles.divider, { exact: true }); }); -test('divider using li', () => { - const view = shallow(<Divider component="li" />); - expect(view).toMatchSnapshot(); +test('Renders with horizontal rule by default', () => { + render(<Divider />); + expect(screen.getByRole('separator')).toContainHTML('<hr class="pf-v6-c-divider" />'); }); -test('divider using div', () => { - const view = shallow(<Divider component="div" />); - expect(view).toMatchSnapshot(); +test('Renders with element passed to component prop', () => { + render(<Divider component="li" />); + expect(screen.getByRole('separator')?.tagName).toBe('LI'); }); -test('vertical divider', () => { - const view = shallow( - <Flex> - <FlexItem>first item</FlexItem> - <Divider isVertical/> - <FlexItem>second item</FlexItem> - </Flex> - ); - expect(view).toMatchSnapshot(); +test('Test default orientation (vertical divider)', () => { + render(<Divider orientation={{ default: 'vertical' }} />); + expect(screen.getByRole('separator')).toHaveClass('pf-m-vertical'); +}); + +test('Test sm orientation', () => { + render(<Divider orientation={{ sm: 'horizontal' }} />); + expect(screen.getByRole('separator')).toHaveClass('pf-m-horizontal-on-sm'); +}); + +test('Test md orientation', () => { + render(<Divider orientation={{ md: 'vertical' }} />); + expect(screen.getByRole('separator')).toHaveClass('pf-m-vertical-on-md'); +}); + +test('Test lg orientation', () => { + render(<Divider orientation={{ lg: 'horizontal' }} />); + expect(screen.getByRole('separator')).toHaveClass('pf-m-horizontal-on-lg'); +}); + +test('Test xl orientation', () => { + render(<Divider orientation={{ xl: 'vertical' }} />); + expect(screen.getByRole('separator')).toHaveClass('pf-m-vertical-on-xl'); +}); + +test('Test 2xl orientation', () => { + render(<Divider orientation={{ '2xl': 'horizontal' }} />); + expect(screen.getByRole('separator')).toHaveClass('pf-m-horizontal-on-2xl'); +}); + +test('Test default inset', () => { + render(<Divider inset={{ default: 'insetNone' }} />); + expect(screen.getByRole('separator')).toHaveClass('pf-m-inset-none'); +}); + +test(`Test all insets`, () => { + const insetValues = Object.values([ + 'insetNone', + 'insetXs', + 'insetSm', + 'insetMd', + 'insetLg', + 'insetXl', + 'inset2xl', + 'inset3xl' + ] as ['insetNone', 'insetXs', 'insetSm', 'insetMd', 'insetLg', 'insetXl', 'inset2xl', 'inset3xl']); + + insetValues.forEach((insetValue) => { + render( + <Divider + inset={{ + default: insetValue, + sm: insetValue, + md: insetValue, + lg: insetValue, + xl: insetValue, + '2xl': insetValue + }} + /> + ); + }); + const modifiers = ['none', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl']; + + modifiers.forEach((modifier, index) => { + const smClass = `pf-m-inset-${modifier}-on-sm`; + const mdClass = `pf-m-inset-${modifier}-on-md`; + const lgClass = `pf-m-inset-${modifier}-on-lg`; + const xlClass = `pf-m-inset-${modifier}-on-xl`; + const xl2Class = `pf-m-inset-${modifier}-on-2xl`; + + expect(screen.getAllByRole('separator')[index]).toHaveClass(smClass, mdClass, lgClass, xlClass, xl2Class); + }); +}); + +test('Does not render with value passed to role by default', () => { + render(<Divider role="presentation" />); + expect(screen.queryByRole('presentation')).not.toBeInTheDocument(); +}); + +test('Renders with value passed to role when component is not "hr"', () => { + render(<Divider component="li" role="presentation" />); + expect(screen.getByRole('presentation')).toBeInTheDocument(); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(<Divider />); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Divider/__tests__/Generated/Divider.test.tsx b/packages/react-core/src/components/Divider/__tests__/Generated/Divider.test.tsx deleted file mode 100644 index 355302f80c5..00000000000 --- a/packages/react-core/src/components/Divider/__tests__/Generated/Divider.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Divider } from '../../Divider'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Divider should match snapshot (auto-generated)', () => { - const view = shallow(<Divider className={"''"} component={'hr'} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Divider/__tests__/Generated/__snapshots__/Divider.test.tsx.snap b/packages/react-core/src/components/Divider/__tests__/Generated/__snapshots__/Divider.test.tsx.snap deleted file mode 100644 index a57dc23d053..00000000000 --- a/packages/react-core/src/components/Divider/__tests__/Generated/__snapshots__/Divider.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Divider should match snapshot (auto-generated) 1`] = ` -<hr - className="pf-c-divider ''" -/> -`; diff --git a/packages/react-core/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap b/packages/react-core/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap index b07274cf593..608fba860e7 100644 --- a/packages/react-core/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap +++ b/packages/react-core/src/components/Divider/__tests__/__snapshots__/Divider.test.tsx.snap @@ -1,37 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`divider using div 1`] = ` -<div - className="pf-c-divider" - role="separator" -/> -`; - -exports[`divider using hr 1`] = ` -<hr - className="pf-c-divider" -/> -`; - -exports[`divider using li 1`] = ` -<li - className="pf-c-divider" - role="separator" -/> -`; - -exports[`vertical divider 1`] = ` -<div - className="pf-l-flex" -> - <FlexItem> - first item - </FlexItem> - <Divider - isVertical={true} +exports[`Matches the snapshot 1`] = ` +<DocumentFragment> + <hr + class="pf-v6-c-divider" /> - <FlexItem> - second item - </FlexItem> -</div> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/Divider/examples/Divider.md b/packages/react-core/src/components/Divider/examples/Divider.md index b62854854a6..a8d039c69e7 100644 --- a/packages/react-core/src/components/Divider/examples/Divider.md +++ b/packages/react-core/src/components/Divider/examples/Divider.md @@ -1,101 +1,62 @@ --- id: Divider section: components -cssPrefix: pf-c-divider +cssPrefix: pf-v6-c-divider propComponents: ['Divider'] --- ## Examples + ### Using hr -```js -import React from 'react'; -import { Divider } from '@patternfly/react-core'; -<Divider /> +```ts file='./DividerUsingHr.tsx' + ``` ### Using li -```js -import React from 'react'; -import { Divider } from '@patternfly/react-core/dist'; - -<ul> - <li>List item one</li> - <Divider component="li"/> - <li>List item two</li> -</ul> + +```ts file='./DividerUsingLi.tsx' + ``` ### Using div -```js -import React from 'react'; -import { Divider } from '@patternfly/react-core'; -<Divider component="div"/> +```ts file='./DividerUsingDiv.tsx' + ``` ### Inset medium -```js -import React from 'react'; -import { Divider } from '@patternfly/react-core'; -<Divider inset={{default: 'insetMd'}}/> +```ts file='./DividerInsetMedium.tsx' + ``` ### Inset at various breakpoints -```js -import React from 'react'; -import { Divider } from '@patternfly/react-core'; - -<Divider - inset={{ - default: 'insetMd', - md: 'insetNone', - lg: 'inset3xl', - xl: 'insetLg' - }} -/> + +```ts file='./DividerInsetVariousBreakpoints.tsx' + ``` ### Vertical in flex layout -```js -import React from 'react'; -import { Divider, Flex, FlexItem } from '@patternfly/react-core'; - -<Flex> - <FlexItem>first item</FlexItem> - <Divider isVertical/> - <FlexItem>second item</FlexItem> -</Flex> + +```ts file='./DividerVerticalFlex.tsx' + +``` + +### Vertical in flex layout, inset small + +```ts file='./DividerVerticalFlexInsetSmall.tsx' + ``` -### Vertical, inset medium in flex layout -```js -import React from 'react'; -import { Divider, Flex, FlexItem } from '@patternfly/react-core'; +### Vertical in flex layout, inset at various breakpoints + +```ts file='./DividerVerticalFlexInsetVariousBreakpoints.tsx' -<Flex> - <FlexItem>first item</FlexItem> - <Divider isVertical inset={{default: 'insetMd'}}/> - <FlexItem>second item</FlexItem> -</Flex> ``` -### Vertical, inset at various breakpoints -```js -import React from 'react'; -import { Divider, Flex, FlexItem } from '@patternfly/react-core'; - -<Flex> - <FlexItem>first item</FlexItem> - <Divider isVertical - inset={{ - default: 'insetMd', - md: 'insetNone', - lg: 'insetSm', - xl: 'insetXs' - }} - /> - <FlexItem>first item</FlexItem> -</Flex> +### Switch orientation at various breakpoints + +```ts file='./DividerOrientationVariousBreakpoints.tsx' + ``` diff --git a/packages/react-core/src/components/Divider/examples/DividerInsetMedium.tsx b/packages/react-core/src/components/Divider/examples/DividerInsetMedium.tsx new file mode 100644 index 00000000000..23ac7a522fd --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerInsetMedium.tsx @@ -0,0 +1,3 @@ +import { Divider } from '@patternfly/react-core'; + +export const DividerInsetMedium: React.FunctionComponent = () => <Divider inset={{ default: 'insetMd' }} />; diff --git a/packages/react-core/src/components/Divider/examples/DividerInsetVariousBreakpoints.tsx b/packages/react-core/src/components/Divider/examples/DividerInsetVariousBreakpoints.tsx new file mode 100644 index 00000000000..32a706ec99b --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerInsetVariousBreakpoints.tsx @@ -0,0 +1,12 @@ +import { Divider } from '@patternfly/react-core'; + +export const DividerInsetVariousBreakpoints: React.FunctionComponent = () => ( + <Divider + inset={{ + default: 'insetMd', + md: 'insetNone', + lg: 'inset3xl', + xl: 'insetLg' + }} + /> +); diff --git a/packages/react-core/src/components/Divider/examples/DividerOrientationVariousBreakpoints.tsx b/packages/react-core/src/components/Divider/examples/DividerOrientationVariousBreakpoints.tsx new file mode 100644 index 00000000000..da3b18a8337 --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerOrientationVariousBreakpoints.tsx @@ -0,0 +1,18 @@ +import { Divider, Flex, FlexItem } from '@patternfly/react-core'; + +export const DividerOrientationVariousBreakpoints: React.FunctionComponent = () => ( + <Flex> + <FlexItem>first item</FlexItem> + <Divider + orientation={{ + default: 'vertical', + sm: 'horizontal', + md: 'vertical', + lg: 'horizontal', + xl: 'vertical', + '2xl': 'horizontal' + }} + /> + <FlexItem>second item</FlexItem> + </Flex> +); diff --git a/packages/react-core/src/components/Divider/examples/DividerUsingDiv.tsx b/packages/react-core/src/components/Divider/examples/DividerUsingDiv.tsx new file mode 100644 index 00000000000..2db47de38eb --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerUsingDiv.tsx @@ -0,0 +1,3 @@ +import { Divider } from '@patternfly/react-core'; + +export const DividerUsingDiv: React.FunctionComponent = () => <Divider component="div" />; diff --git a/packages/react-core/src/components/Divider/examples/DividerUsingHr.tsx b/packages/react-core/src/components/Divider/examples/DividerUsingHr.tsx new file mode 100644 index 00000000000..90b2418a27b --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerUsingHr.tsx @@ -0,0 +1,3 @@ +import { Divider } from '@patternfly/react-core'; + +export const DividerUsingHr: React.FunctionComponent = () => <Divider />; diff --git a/packages/react-core/src/components/Divider/examples/DividerUsingLi.tsx b/packages/react-core/src/components/Divider/examples/DividerUsingLi.tsx new file mode 100644 index 00000000000..0d6e4584f65 --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerUsingLi.tsx @@ -0,0 +1,9 @@ +import { Divider } from '@patternfly/react-core'; + +export const DividerUsingLi: React.FunctionComponent = () => ( + <ul role="list"> + <li>List item one</li> + <Divider component="li" role="none" /> + <li>List item two</li> + </ul> +); diff --git a/packages/react-core/src/components/Divider/examples/DividerVerticalFlex.tsx b/packages/react-core/src/components/Divider/examples/DividerVerticalFlex.tsx new file mode 100644 index 00000000000..47a40933628 --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerVerticalFlex.tsx @@ -0,0 +1,13 @@ +import { Divider, Flex, FlexItem } from '@patternfly/react-core'; + +export const DividerVerticalFlex: React.FunctionComponent = () => ( + <Flex> + <FlexItem>first item</FlexItem> + <Divider + orientation={{ + default: 'vertical' + }} + /> + <FlexItem>second item</FlexItem> + </Flex> +); diff --git a/packages/react-core/src/components/Divider/examples/DividerVerticalFlexInsetSmall.tsx b/packages/react-core/src/components/Divider/examples/DividerVerticalFlexInsetSmall.tsx new file mode 100644 index 00000000000..0ad28729feb --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerVerticalFlexInsetSmall.tsx @@ -0,0 +1,14 @@ +import { Divider, Flex, FlexItem } from '@patternfly/react-core'; + +export const DividerVerticalFlexInsetSmall: React.FunctionComponent = () => ( + <Flex> + <FlexItem>first item</FlexItem> + <Divider + orientation={{ + default: 'vertical' + }} + inset={{ default: 'insetSm' }} + /> + <FlexItem>second item</FlexItem> + </Flex> +); diff --git a/packages/react-core/src/components/Divider/examples/DividerVerticalFlexInsetVariousBreakpoints.tsx b/packages/react-core/src/components/Divider/examples/DividerVerticalFlexInsetVariousBreakpoints.tsx new file mode 100644 index 00000000000..7f1c67baca9 --- /dev/null +++ b/packages/react-core/src/components/Divider/examples/DividerVerticalFlexInsetVariousBreakpoints.tsx @@ -0,0 +1,19 @@ +import { Divider, Flex, FlexItem } from '@patternfly/react-core'; + +export const DividerVerticalFlexInsetVariousBreakpoints: React.FunctionComponent = () => ( + <Flex> + <FlexItem>first item</FlexItem> + <Divider + orientation={{ + default: 'vertical' + }} + inset={{ + default: 'insetMd', + md: 'insetNone', + lg: 'insetSm', + xl: 'insetXs' + }} + /> + <FlexItem>second item</FlexItem> + </Flex> +); diff --git a/packages/react-core/src/components/DragDrop/DragDrop.tsx b/packages/react-core/src/components/DragDrop/DragDrop.tsx deleted file mode 100644 index b2dd873b2f1..00000000000 --- a/packages/react-core/src/components/DragDrop/DragDrop.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; - -interface DraggableItemPosition { - /** Parent droppableId */ - droppableId: string; - /** Index of item in parent Droppable */ - index: number; -} - -export const DragDropContext = React.createContext({ - onDrag: (_source: DraggableItemPosition) => true as boolean, - onDragMove: (_source: DraggableItemPosition, _dest?: DraggableItemPosition) => {}, - onDrop: (_source: DraggableItemPosition, _dest?: DraggableItemPosition) => false as boolean -}); - -interface DragDropProps { - /** Potentially Droppable and Draggable children */ - children?: React.ReactNode; - /** Callback for drag event. Return true to allow drag, false to disallow. */ - onDrag?: (source: DraggableItemPosition) => boolean; - /** Callback on mouse move while dragging. */ - onDragMove?: (source: DraggableItemPosition, dest?: DraggableItemPosition) => void; - /** Callback for drop event. Return true to allow drop, false to disallow. */ - onDrop?: (source: DraggableItemPosition, dest?: DraggableItemPosition) => boolean; -} - -export const DragDrop: React.FunctionComponent<DragDropProps> = ({ - children, - onDrag = () => true, - onDragMove = () => {}, - onDrop = () => false -}: DragDropProps) => ( - <DragDropContext.Provider value={{ onDrag, onDragMove, onDrop }}>{children}</DragDropContext.Provider> -); -DragDrop.displayName = 'DragDrop'; diff --git a/packages/react-core/src/components/DragDrop/Draggable.tsx b/packages/react-core/src/components/DragDrop/Draggable.tsx deleted file mode 100644 index 30a3438018b..00000000000 --- a/packages/react-core/src/components/DragDrop/Draggable.tsx +++ /dev/null @@ -1,327 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/DragDrop/drag-drop'; -import { DroppableContext } from './DroppableContext'; -import { DragDropContext } from './DragDrop'; - -export interface DraggableProps extends React.HTMLProps<HTMLDivElement> { - /** Content rendered inside DragDrop */ - children?: React.ReactNode; - /** Don't wrap the component in a div. Requires passing a single child. */ - hasNoWrapper?: boolean; - /** Class to add to outer div */ - className?: string; -} - -// Browsers really like being different from each other. -function getDefaultBackground() { - const div = document.createElement('div'); - document.head.appendChild(div); - const bg = window.getComputedStyle(div).backgroundColor; - document.head.removeChild(div); - return bg; -} - -function getInheritedBackgroundColor(el: HTMLElement): string { - const defaultStyle = getDefaultBackground(); - const backgroundColor = window.getComputedStyle(el).backgroundColor; - - if (backgroundColor !== defaultStyle) { - return backgroundColor; - } else if (!el.parentElement) { - return defaultStyle; - } - - return getInheritedBackgroundColor(el.parentElement); -} - -function removeBlankDiv(node: HTMLElement) { - if (node.getAttribute('blankDiv') === 'true') { - // eslint-disable-next-line @typescript-eslint/prefer-for-of - for (let i = 0; i < node.children.length; i++) { - const child = node.children[i]; - if (child.getAttribute('blankDiv') === 'true') { - node.removeChild(child); - node.setAttribute('blankDiv', 'false'); - break; - } - } - } -} - -interface DroppableItem { - node: HTMLElement; - rect: DOMRect; - isDraggingHost: boolean; - draggableNodes: HTMLElement[]; - draggableNodesRects: DOMRect[]; -} - -// Reset per-element state -function resetDroppableItem(droppableItem: DroppableItem) { - removeBlankDiv(droppableItem.node); - droppableItem.node.classList.remove(styles.modifiers.dragging); - droppableItem.node.classList.remove(styles.modifiers.dragOutside); - droppableItem.draggableNodes.forEach((n, i) => { - n.style.transform = ''; - n.style.transition = ''; - droppableItem.draggableNodesRects[i] = n.getBoundingClientRect(); - }); -} - -function overlaps(ev: MouseEvent, rect: DOMRect) { - return ( - ev.clientX > rect.x && ev.clientX < rect.x + rect.width && ev.clientY > rect.y && ev.clientY < rect.y + rect.height - ); -} - -export const Draggable: React.FunctionComponent<DraggableProps> = ({ - className, - children, - style: styleProp = {}, - hasNoWrapper = false, - ...props -}: DraggableProps) => { - /* eslint-disable prefer-const */ - let [style, setStyle] = React.useState(styleProp); - /* eslint-enable prefer-const */ - const [isDragging, setIsDragging] = React.useState(false); - const [isValidDrag, setIsValidDrag] = React.useState(true); - const { zone, droppableId } = React.useContext(DroppableContext); - const { onDrag, onDragMove, onDrop } = React.useContext(DragDropContext); - // Some state is better just to leave as vars passed around between various callbacks - // You can only drag around one item at a time anyways... - let startX = 0; - let startY = 0; - let index: number = null; // Index of this draggable - let hoveringDroppable: HTMLElement; - let hoveringIndex: number = null; - let mouseMoveListener: EventListener; - let mouseUpListener: EventListener; - // Makes it so dragging the _bottom_ of the item over the halfway of another moves it - let startYOffset = 0; - - // After item returning to where it started animation completes - const onTransitionEnd = (_ev: React.TransitionEvent<HTMLElement>) => { - if (isDragging) { - setIsDragging(false); - setStyle(styleProp); - } - }; - - function getSourceAndDest() { - const hoveringDroppableId = hoveringDroppable ? hoveringDroppable.getAttribute('data-pf-droppableid') : null; - const source = { - droppableId, - index - }; - const dest = - hoveringDroppableId !== null && hoveringIndex !== null - ? { - droppableId: hoveringDroppableId, - index: hoveringIndex - } - : undefined; - return { source, dest, hoveringDroppableId }; - } - - const onMouseUpWhileDragging = (droppableItems: DroppableItem[]) => { - droppableItems.forEach(resetDroppableItem); - document.removeEventListener('mousemove', mouseMoveListener); - document.removeEventListener('mouseup', mouseUpListener); - document.removeEventListener('contextmenu', mouseUpListener); - const { source, dest, hoveringDroppableId } = getSourceAndDest(); - const consumerReordered = onDrop(source, dest); - if (consumerReordered && droppableId === hoveringDroppableId) { - setIsDragging(false); - setStyle(styleProp); - } else if (!consumerReordered) { - // Animate item returning to where it started - setStyle({ - ...style, - transition: 'transform 0.5s cubic-bezier(0.2, 1, 0.1, 1) 0s', - transform: '', - background: styleProp.background, - boxShadow: styleProp.boxShadow - }); - } - }; - - // This is where the magic happens - const onMouseMoveWhileDragging = (ev: MouseEvent, droppableItems: DroppableItem[], blankDivRect: DOMRect) => { - // Compute each time what droppable node we are hovering over - hoveringDroppable = null; - droppableItems.forEach(droppableItem => { - const { node, rect, isDraggingHost, draggableNodes, draggableNodesRects } = droppableItem; - if (overlaps(ev, rect)) { - // Add valid dropzone style - node.classList.remove(styles.modifiers.dragOutside); - hoveringDroppable = node; - // Check if we need to add a blank div row - if (node.getAttribute('blankDiv') !== 'true' && !isDraggingHost) { - const blankDiv = document.createElement('div'); - blankDiv.setAttribute('blankDiv', 'true'); // Makes removing easier - let blankDivPos = -1; - for (let i = 0; i < draggableNodes.length; i++) { - const childRect = draggableNodesRects[i]; - const isLast = i === draggableNodes.length - 1; - const startOverlaps = childRect.y >= startY - startYOffset; - if ((startOverlaps || isLast) && blankDivPos === -1) { - if (isLast && !startOverlaps) { - draggableNodes[i].after(blankDiv); - } else { - draggableNodes[i].before(blankDiv); - } - blankDiv.style.height = `${blankDivRect.height}px`; - blankDiv.style.width = `${blankDivRect.width}px`; - node.setAttribute('blankDiv', 'true'); // Makes removing easier - blankDivPos = i; - } - if (blankDivPos !== -1) { - childRect.y += blankDivRect.height; - } - } - // Insert so drag + drop behavior matches single-list case - draggableNodes.splice(blankDivPos, 0, blankDiv); - draggableNodesRects.splice(blankDivPos, 0, blankDivRect); - // Extend hitbox of droppable zone - rect.height += blankDivRect.height; - } - } else { - resetDroppableItem(droppableItem); - node.classList.add(styles.modifiers.dragging); - node.classList.add(styles.modifiers.dragOutside); - } - }); - - // Move hovering draggable and style it based on cursor position - setStyle({ - ...style, - transform: `translate(${ev.pageX - startX}px, ${ev.pageY - startY}px)` - }); - setIsValidDrag(Boolean(hoveringDroppable)); - - // Iterate through sibling draggable nodes to reposition them and store correct hoveringIndex for onDrop - hoveringIndex = null; - if (hoveringDroppable) { - const { draggableNodes, draggableNodesRects } = droppableItems.find(item => item.node === hoveringDroppable); - let lastTranslate = 0; - draggableNodes.forEach((n, i) => { - n.style.transition = 'transform 0.5s cubic-bezier(0.2, 1, 0.1, 1) 0s'; - const rect = draggableNodesRects[i]; - const halfway = rect.y + rect.height / 2; - let translateY = 0; - // Use offset for more interactive translations - if (startY < halfway && ev.pageY + (blankDivRect.height - startYOffset) > halfway) { - translateY -= blankDivRect.height; - } else if (startY >= halfway && ev.pageY - startYOffset <= halfway) { - translateY += blankDivRect.height; - } - // Clever way to find item currently hovering over - if ((translateY <= lastTranslate && translateY < 0) || (translateY > lastTranslate && translateY > 0)) { - hoveringIndex = i; - } - n.style.transform = `translate(0, ${translateY}px`; - lastTranslate = translateY; - }); - } - - const { source, dest } = getSourceAndDest(); - onDragMove(source, dest); - }; - - const onDragStart = (ev: React.DragEvent<HTMLElement>) => { - // Default HTML drag and drop doesn't allow us to change what the thing - // being dragged looks like. Because of this we'll use prevent the default - // and use `mouseMove` and `mouseUp` instead - ev.preventDefault(); - if (isDragging) { - // still in animation - return; - } - - // Cache droppable and draggable nodes and their bounding rects - const dragging = ev.target as HTMLElement; - const rect = dragging.getBoundingClientRect(); - const droppableNodes = Array.from(document.querySelectorAll(`[data-pf-droppable="${zone}"]`)) as HTMLElement[]; - const droppableItems = droppableNodes.reduce((acc, cur) => { - cur.classList.add(styles.modifiers.dragging); - const draggableNodes = Array.from(cur.querySelectorAll(`[data-pf-draggable-zone="${zone}"]`)) as HTMLElement[]; - const isDraggingHost = cur.contains(dragging); - if (isDraggingHost) { - index = draggableNodes.indexOf(dragging); - } - const droppableItem = { - node: cur, - rect: cur.getBoundingClientRect(), - isDraggingHost, - // We don't want styles to apply to the left behind div in onMouseMoveWhileDragging - draggableNodes: draggableNodes.map(node => (node === dragging ? node.cloneNode(false) : node)), - draggableNodesRects: draggableNodes.map(node => node.getBoundingClientRect()) - }; - acc.push(droppableItem); - return acc; - }, []); - - if (!onDrag({ droppableId, index })) { - // Consumer disallowed drag - return; - } - - // Set initial style so future style mods take effect - style = { - ...style, - top: rect.y, - left: rect.x, - width: rect.width, - height: rect.height, - '--pf-c-draggable--m-dragging--BackgroundColor': getInheritedBackgroundColor(dragging), - position: 'fixed', - zIndex: 5000 - } as any; - setStyle(style); - // Store event details - startX = ev.pageX; - startY = ev.pageY; - startYOffset = startY - rect.y; - setIsDragging(true); - mouseMoveListener = ev => onMouseMoveWhileDragging(ev as MouseEvent, droppableItems, rect); - mouseUpListener = () => onMouseUpWhileDragging(droppableItems); - document.addEventListener('mousemove', mouseMoveListener); - document.addEventListener('mouseup', mouseUpListener); - // Comment out this line to debug while dragging by right clicking - // document.addEventListener('contextmenu', mouseUpListener); - }; - - const childProps = { - 'data-pf-draggable-zone': isDragging ? null : zone, - draggable: true, - className: css( - styles.draggable, - isDragging && styles.modifiers.dragging, - !isValidDrag && styles.modifiers.dragOutside, - className - ), - onDragStart, - onTransitionEnd, - style, - ...props - }; - - return ( - <React.Fragment> - {/* Leave behind blank spot per-design */} - {isDragging && ( - <div draggable {...props} style={{ ...styleProp, visibility: 'hidden' }}> - {children} - </div> - )} - {hasNoWrapper ? ( - React.cloneElement(children as React.ReactElement, childProps) - ) : ( - <div {...childProps}>{children}</div> - )} - </React.Fragment> - ); -}; -Draggable.displayName = 'Draggable'; diff --git a/packages/react-core/src/components/DragDrop/Droppable.tsx b/packages/react-core/src/components/DragDrop/Droppable.tsx deleted file mode 100644 index aaf1032a810..00000000000 --- a/packages/react-core/src/components/DragDrop/Droppable.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/DragDrop/drag-drop'; -import { DroppableContext } from './DroppableContext'; - -interface DroppableProps extends React.HTMLProps<HTMLDivElement> { - /** Content rendered inside DragDrop */ - children?: React.ReactNode; - /** Class to add to outer div */ - className?: string; - /** Name of zone that items can be dragged between. Should specify if there is more than one Droppable on the page. */ - zone?: string; - /** Id to be passed back on drop events */ - droppableId?: string; - /** Don't wrap the component in a div. Requires passing a single child. */ - hasNoWrapper?: boolean; -} - -export const Droppable: React.FunctionComponent<DroppableProps> = ({ - className, - children, - zone = 'defaultZone', - droppableId = 'defaultId', - hasNoWrapper = false, - ...props -}: DroppableProps) => { - const childProps = { - 'data-pf-droppable': zone, - 'data-pf-droppableid': droppableId, - // if has no wrapper is set, don't overwrite children className with the className prop - className: - hasNoWrapper && React.Children.count(children) === 1 - ? css(styles.droppable, className, (children as React.ReactElement).props.className) - : css(styles.droppable, className), - ...props - }; - - return ( - <DroppableContext.Provider value={{ zone, droppableId }}> - {hasNoWrapper ? ( - React.cloneElement(children as React.ReactElement, childProps) - ) : ( - <div {...childProps}>{children}</div> - )} - </DroppableContext.Provider> - ); -}; -Droppable.displayName = 'Droppable'; diff --git a/packages/react-core/src/components/DragDrop/DroppableContext.ts b/packages/react-core/src/components/DragDrop/DroppableContext.ts deleted file mode 100644 index 888cb4fc66f..00000000000 --- a/packages/react-core/src/components/DragDrop/DroppableContext.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from 'react'; - -export const DroppableContext = React.createContext({ - zone: 'defaultDroppableZone', - droppableId: 'defaultDroppableId' -}); diff --git a/packages/react-core/src/components/DragDrop/__tests__/DragDrop.test.tsx b/packages/react-core/src/components/DragDrop/__tests__/DragDrop.test.tsx deleted file mode 100644 index 5dcbf018d62..00000000000 --- a/packages/react-core/src/components/DragDrop/__tests__/DragDrop.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import { DragDrop, Draggable, Droppable } from '../'; - -test('renders some divs', () => { - const view = shallow( - <DragDrop> - <Droppable droppableId="dropzone"> - <Draggable draggableId="draggable1"> - item 1 - </Draggable> - <Draggable draggableId="draggable2"> - item 2 - </Draggable> - </Droppable> - </DragDrop> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/DragDrop/__tests__/__snapshots__/DragDrop.test.tsx.snap b/packages/react-core/src/components/DragDrop/__tests__/__snapshots__/DragDrop.test.tsx.snap deleted file mode 100644 index 09da4f81e90..00000000000 --- a/packages/react-core/src/components/DragDrop/__tests__/__snapshots__/DragDrop.test.tsx.snap +++ /dev/null @@ -1,28 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renders some divs 1`] = ` -<ContextProvider - value={ - Object { - "onDrag": [Function], - "onDragMove": [Function], - "onDrop": [Function], - } - } -> - <Droppable - droppableId="dropzone" - > - <Draggable - draggableId="draggable1" - > - item 1 - </Draggable> - <Draggable - draggableId="draggable2" - > - item 2 - </Draggable> - </Droppable> -</ContextProvider> -`; diff --git a/packages/react-core/src/components/DragDrop/examples/DragDrop.md b/packages/react-core/src/components/DragDrop/examples/DragDrop.md deleted file mode 100644 index c22c0b47c33..00000000000 --- a/packages/react-core/src/components/DragDrop/examples/DragDrop.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -id: Drag and drop -section: components -propComponents: [ - DragDrop, - Draggable, - Droppable, - DraggableItemPosition -] -beta: true ---- - -You can use `DragDrop` to move items in or between lists. `DragDrop`s should contain `Droppable`s which contain `Draggable`s. - -```js noLive -import React from 'react'; -import { DragDrop, Draggable, Droppable } from '@patternfly/react-core'; - -<DragDrop> {/* DragDrop houses the context for dragging and dropping */} - <Droppable> - <Draggable> - You can put anything here! It will be wrapped in a styled div. - </Draggable> - <Draggable> - You can have as many Draggables as you like. - </Draggable> - </Droppable> - <Droppable> {/* You can also have many droppables! */} - <Draggable /> - </Droppable> -</DragDrop> -``` -Note: Keyboard accessibility and screen reader accessibility are still in development. - -## Examples -### Basic - -```js -import React from 'react'; -import { DragDrop, Draggable, Droppable } from '@patternfly/react-core'; - -const getItems = count => - Array.from({ length: count }, (v, k) => k).map(k => ({ - id: `item-${k}`, - content: `item ${k} `.repeat(k === 4 ? 20 : 1) - })); - -const reorder = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); - return result; -}; - -Basic = () => { - const [items, setItems] = React.useState(getItems(10)); - - function onDrop(source, dest) { - if (dest) { - const newItems = reorder( - items, - source.index, - dest.index - ); - setItems(newItems); - - return true; - } - return false; - } - - return ( - <DragDrop onDrop={onDrop}> - <Droppable> - {items.map(({ id, content }, i) => - <Draggable key={i} style={{ padding: '8px' }}> - {content} - </Draggable> - )} - </Droppable> - </DragDrop> - ); -} -``` - -### Multiple lists - -```js -import React from 'react'; -import { DragDrop, Draggable, Droppable, Split, SplitItem } from '@patternfly/react-core'; - -const getItems = (count, start) => - Array.from({ length: count }, (v, k) => k).map(k => ({ - id: `item-${k + start}`, - content: `item ${k + start} `.repeat(k === 4 ? 20 : 1) - })); - -const reorder = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); - return result; -}; - -const move = (source, destination, sourceIndex, destIndex) => { - const sourceClone = Array.from(source); - const destClone = Array.from(destination); - const [removed] = sourceClone.splice(sourceIndex, 1); - destClone.splice(destIndex, 0, removed); - return [sourceClone, destClone]; -}; - -MultiList = () => { - const [items, setItems] = React.useState({ - items1: getItems(10, 0), - items2: getItems(5, 10) - }); - - function onDrop(source, dest) { - console.log(source, dest); - if (dest) { - if (source.droppableId === dest.droppableId) { - const newItems = reorder( - source.droppableId === 'items1' ? items.items1 : items.items2, - source.index, - dest.index - ); - if (source.droppableId === 'items1') { - setItems({ - items1: newItems, - items2: items.items2 - }); - } else { - setItems({ - items1: items.items1, - items2: newItems - }); - } - } else { - const [newItems1, newItems2] = move( - source.droppableId === 'items1' ? items.items1 : items.items2, - dest.droppableId === 'items1' ? items.items1 : items.items2, - source.index, - dest.index - ); - setItems({ - items1: source.droppableId === 'items1' ? newItems1 : newItems2, - items2: dest.droppableId === 'items1' ? newItems1 : newItems2 - }); - } - return true; - } - return false; - } - - return ( - <DragDrop onDrop={onDrop}> - <Split hasGutter> - {Object.entries(items).map(([key, subitems]) => - <SplitItem key={key} style={{ flex: 1 }}> - <Droppable zone="multizone" droppableId={key}> - {subitems.map(({ id, content }, i) => - <Draggable key={id} style={{ padding: '8px' }}> - {content} - </Draggable> - )} - </Droppable> - </SplitItem> - )} - </Split> - </DragDrop> - ); -} -``` - diff --git a/packages/react-core/src/components/DragDrop/index.ts b/packages/react-core/src/components/DragDrop/index.ts deleted file mode 100644 index 032ae9dfe38..00000000000 --- a/packages/react-core/src/components/DragDrop/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './DragDrop'; -export * from './Draggable'; -export * from './Droppable'; diff --git a/packages/react-core/src/components/Drawer/Drawer.tsx b/packages/react-core/src/components/Drawer/Drawer.tsx index ab2a0404892..eaa6c58dfcd 100644 --- a/packages/react-core/src/components/Drawer/Drawer.tsx +++ b/packages/react-core/src/components/Drawer/Drawer.tsx @@ -1,43 +1,53 @@ -import * as React from 'react'; +import { createContext, useRef } from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; export enum DrawerColorVariant { default = 'default', - light200 = 'light-200' + secondary = 'secondary', + /** + * @deprecated `DrawerColorVariant.noBackground` is deprecated. Use the `isPlain` prop on `DrawerPanelContent` and the `DrawerSection`instead. + */ + noBackground = 'no-background' } export interface DrawerProps extends React.HTMLProps<HTMLDivElement> { /** Additional classes added to the Drawer. */ className?: string; - /** Content rendered in the left hand panel */ + /** Content rendered in the drawer panel */ children?: React.ReactNode; /** Indicates if the drawer is expanded */ isExpanded?: boolean; /** Indicates if the content element and panel element are displayed side by side. */ isInline?: boolean; + /** @beta Indicates if the drawer will have pill styles */ + isPill?: boolean; /** Indicates if the drawer will always show both content and panel. */ isStatic?: boolean; - /** Position of the drawer panel */ - position?: 'left' | 'right' | 'bottom'; + /** Position of the drawer panel. left and right are deprecated, use start and end instead. */ + position?: 'start' | 'end' | 'bottom' | 'left' | 'right'; /** Callback when drawer panel is expanded after waiting 250ms for animation to complete. */ - onExpand?: () => void; + onExpand?: (event: KeyboardEvent | React.MouseEvent | React.TransitionEvent) => void; } export interface DrawerContextProps { isExpanded: boolean; isStatic: boolean; - onExpand?: () => void; + onExpand?: (event: KeyboardEvent | React.MouseEvent | React.TransitionEvent) => void; position?: string; - drawerRef?: React.RefObject<HTMLDivElement>; + drawerRef?: React.RefObject<HTMLDivElement | null>; + drawerContentRef?: React.RefObject<HTMLDivElement | null>; + isInline: boolean; } -export const DrawerContext = React.createContext<Partial<DrawerContextProps>>({ +export const DrawerContext = createContext<Partial<DrawerContextProps>>({ isExpanded: false, isStatic: false, onExpand: () => {}, - position: 'right', - drawerRef: null + position: 'end', + drawerRef: null, + drawerContentRef: null, + isInline: false }); export const Drawer: React.FunctionComponent<DrawerProps> = ({ @@ -45,21 +55,25 @@ export const Drawer: React.FunctionComponent<DrawerProps> = ({ children, isExpanded = false, isInline = false, + isPill = false, isStatic = false, - position = 'right', + position = 'end', onExpand = () => {}, ...props }: DrawerProps) => { - const drawerRef = React.useRef<HTMLDivElement>(); + const drawerRef = useRef<HTMLDivElement>(undefined); + const drawerContentRef = useRef<HTMLDivElement>(undefined); + return ( - <DrawerContext.Provider value={{ isExpanded, isStatic, onExpand, position, drawerRef }}> + <DrawerContext.Provider value={{ isExpanded, isStatic, onExpand, position, drawerRef, drawerContentRef, isInline }}> <div className={css( styles.drawer, isExpanded && styles.modifiers.expanded, isInline && styles.modifiers.inline, + isPill && styles.modifiers.pill, isStatic && styles.modifiers.static, - position === 'left' && styles.modifiers.panelLeft, + (position === 'left' || position === 'start') && styles.modifiers.panelLeft, position === 'bottom' && styles.modifiers.panelBottom, className )} diff --git a/packages/react-core/src/components/Drawer/DrawerActions.tsx b/packages/react-core/src/components/Drawer/DrawerActions.tsx index 0d1307665d2..97d4367861c 100644 --- a/packages/react-core/src/components/Drawer/DrawerActions.tsx +++ b/packages/react-core/src/components/Drawer/DrawerActions.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; @@ -9,8 +8,7 @@ export interface DrawerActionsProps extends React.HTMLProps<HTMLDivElement> { children?: React.ReactNode; } -export const DrawerActions: React.SFC<DrawerActionsProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars +export const DrawerActions: React.FunctionComponent<DrawerActionsProps> = ({ className = '', children, ...props diff --git a/packages/react-core/src/components/Drawer/DrawerCloseButton.tsx b/packages/react-core/src/components/Drawer/DrawerCloseButton.tsx index 333a02d1b6e..cbab0ae4ac3 100644 --- a/packages/react-core/src/components/Drawer/DrawerCloseButton.tsx +++ b/packages/react-core/src/components/Drawer/DrawerCloseButton.tsx @@ -1,8 +1,7 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; import { Button } from '../Button'; -import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; +import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon'; export interface DrawerCloseButtonProps extends React.HTMLProps<HTMLDivElement> { /** Additional classes added to the drawer close button outer <div>. */ @@ -13,17 +12,14 @@ export interface DrawerCloseButtonProps extends React.HTMLProps<HTMLDivElement> 'aria-label'?: string; } -export const DrawerCloseButton: React.SFC<DrawerCloseButtonProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars +export const DrawerCloseButton: React.FunctionComponent<DrawerCloseButtonProps> = ({ className = '', onClose = () => undefined as any, 'aria-label': ariaLabel = 'Close drawer panel', ...props }: DrawerCloseButtonProps) => ( <div className={css(styles.drawerClose, className)} {...props}> - <Button variant="plain" onClick={onClose} aria-label={ariaLabel}> - <TimesIcon /> - </Button> + <Button variant="plain" onClick={onClose} aria-label={ariaLabel} icon={<RhMicronsCloseIcon />} /> </div> ); DrawerCloseButton.displayName = 'DrawerCloseButton'; diff --git a/packages/react-core/src/components/Drawer/DrawerContent.tsx b/packages/react-core/src/components/Drawer/DrawerContent.tsx index b19d969b302..a489316842d 100644 --- a/packages/react-core/src/components/Drawer/DrawerContent.tsx +++ b/packages/react-core/src/components/Drawer/DrawerContent.tsx @@ -1,8 +1,14 @@ -import * as React from 'react'; +import { useContext } from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; import { DrawerMain } from './DrawerMain'; -import { DrawerColorVariant } from './Drawer'; +import { DrawerContext } from './Drawer'; + +export enum DrawerContentColorVariant { + default = 'default', + primary = 'primary', + secondary = 'secondary' +} export interface DrawerContentProps extends React.HTMLProps<HTMLDivElement> { /** Additional classes added to the Drawer. */ @@ -12,29 +18,34 @@ export interface DrawerContentProps extends React.HTMLProps<HTMLDivElement> { /** Content rendered in the drawer panel. */ panelContent: React.ReactNode; /** Color variant of the background of the drawer panel */ - colorVariant?: DrawerColorVariant | 'light-200' | 'default'; + colorVariant?: DrawerContentColorVariant | 'default' | 'primary' | 'secondary'; } -export const DrawerContent: React.SFC<DrawerContentProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - className = '', +export const DrawerContent: React.FunctionComponent<DrawerContentProps> = ({ + className, children, panelContent, - colorVariant = DrawerColorVariant.default, + colorVariant = DrawerContentColorVariant.default, ...props -}: DrawerContentProps) => ( - <DrawerMain> - <div - className={css( - styles.drawerContent, - colorVariant === DrawerColorVariant.light200 && styles.modifiers.light_200, - className - )} - {...props} - > - {children} - </div> - {panelContent} - </DrawerMain> -); +}: DrawerContentProps) => { + const { drawerContentRef } = useContext(DrawerContext); + + return ( + <DrawerMain> + <div + className={css( + styles.drawerContent, + colorVariant === DrawerContentColorVariant.primary && styles.modifiers.primary, + colorVariant === DrawerContentColorVariant.secondary && styles.modifiers.secondary, + className + )} + ref={drawerContentRef} + {...props} + > + {children} + </div> + {panelContent} + </DrawerMain> + ); +}; DrawerContent.displayName = 'DrawerContent'; diff --git a/packages/react-core/src/components/Drawer/DrawerContentBody.tsx b/packages/react-core/src/components/Drawer/DrawerContentBody.tsx index 3f87ad59bb9..a522457b4a2 100644 --- a/packages/react-core/src/components/Drawer/DrawerContentBody.tsx +++ b/packages/react-core/src/components/Drawer/DrawerContentBody.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; @@ -11,8 +10,7 @@ export interface DrawerContentBodyProps extends React.HTMLProps<HTMLDivElement> hasPadding?: boolean; } -export const DrawerContentBody: React.SFC<DrawerContentBodyProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars +export const DrawerContentBody: React.FunctionComponent<DrawerContentBodyProps> = ({ className = '', children, hasPadding = false, diff --git a/packages/react-core/src/components/Drawer/DrawerHead.tsx b/packages/react-core/src/components/Drawer/DrawerHead.tsx index 8c67abe95ba..703531699ea 100644 --- a/packages/react-core/src/components/Drawer/DrawerHead.tsx +++ b/packages/react-core/src/components/Drawer/DrawerHead.tsx @@ -1,28 +1,20 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; -import { DrawerPanelBody } from './DrawerPanelBody'; export interface DrawerHeadProps extends React.HTMLProps<HTMLDivElement> { /** Additional classes added to the drawer head. */ className?: string; /** Content to be rendered in the drawer head */ children?: React.ReactNode; - /** Indicates if there should be no padding around the drawer panel body of the head*/ - hasNoPadding?: boolean; } -export const DrawerHead: React.SFC<DrawerHeadProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars +export const DrawerHead: React.FunctionComponent<DrawerHeadProps> = ({ className = '', children, - hasNoPadding = false, ...props }: DrawerHeadProps) => ( - <DrawerPanelBody hasNoPadding={hasNoPadding}> - <div className={css(styles.drawerHead, className)} {...props}> - {children} - </div> - </DrawerPanelBody> + <div className={css(styles.drawerHead, className)} {...props}> + {children} + </div> ); DrawerHead.displayName = 'DrawerHead'; diff --git a/packages/react-core/src/components/Drawer/DrawerMain.tsx b/packages/react-core/src/components/Drawer/DrawerMain.tsx index 50c264e6339..1cda6baddab 100644 --- a/packages/react-core/src/components/Drawer/DrawerMain.tsx +++ b/packages/react-core/src/components/Drawer/DrawerMain.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; @@ -9,8 +8,7 @@ export interface DrawerMainProps extends React.HTMLProps<HTMLDivElement> { children?: React.ReactNode; } -export const DrawerMain: React.SFC<DrawerMainProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars +export const DrawerMain: React.FunctionComponent<DrawerMainProps> = ({ className = '', children, ...props diff --git a/packages/react-core/src/components/Drawer/DrawerPanelBody.tsx b/packages/react-core/src/components/Drawer/DrawerPanelBody.tsx index ce554c9d4de..9b6ca99e73e 100644 --- a/packages/react-core/src/components/Drawer/DrawerPanelBody.tsx +++ b/packages/react-core/src/components/Drawer/DrawerPanelBody.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; @@ -11,8 +10,7 @@ export interface DrawerPanelBodyProps extends React.HTMLProps<HTMLDivElement> { hasNoPadding?: boolean; } -export const DrawerPanelBody: React.SFC<DrawerPanelBodyProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars +export const DrawerPanelBody: React.FunctionComponent<DrawerPanelBodyProps> = ({ className = '', children, hasNoPadding = false, diff --git a/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx b/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx index 208bf85c79c..2933af16965 100644 --- a/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx +++ b/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx @@ -1,10 +1,30 @@ -import * as React from 'react'; +import { Fragment, useCallback, useContext, useEffect, useRef, useState } from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; import { DrawerColorVariant, DrawerContext } from './Drawer'; -import { formatBreakpointMods } from '../../helpers/util'; +import { formatBreakpointMods, getLanguageDirection } from '../../helpers/util'; +import { useSSRSafeId } from '../../helpers'; +import { FocusTrap } from '../../helpers/FocusTrap/FocusTrap'; +import cssPanelMdFlexBasis from '@patternfly/react-tokens/dist/esm/c_drawer__panel_md_FlexBasis'; +import cssPanelMdFlexBasisMin from '@patternfly/react-tokens/dist/esm/c_drawer__panel_md_FlexBasis_min'; +import cssPanelMdFlexBasisMax from '@patternfly/react-tokens/dist/esm/c_drawer__panel_md_FlexBasis_max'; -export interface DrawerPanelContentProps extends React.HTMLProps<HTMLDivElement> { +export interface DrawerPanelFocusTrapObject { + /** Enables a focus trap on the drawer panel content. This will also automatically + * handle focus management when the panel expands and when it collapses. Do not pass + * this prop if the isStatic prop on the drawer component is true. + */ + enabled?: boolean; + /** The element to focus when the drawer panel content expands. By default the + * first focusable element will receive focus. If there are no focusable elements, the + * panel itself will receive focus. + */ + elementToFocusOnExpand?: HTMLElement | SVGElement | string; + /** One or more id's to use for the drawer panel content's accessible label. */ + 'aria-labelledby'?: string; +} + +export interface DrawerPanelContentProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onResize'> { /** Additional classes added to the drawer. */ className?: string; /** ID of the drawer panel */ @@ -15,67 +35,157 @@ export interface DrawerPanelContentProps extends React.HTMLProps<HTMLDivElement> hasNoBorder?: boolean; /** Flag indicating that the drawer panel should be resizable. */ isResizable?: boolean; + /** @beta Flag indicating that the drawer panel should disable glass styles. This prop is intended to work with isPill drawers. */ + hasNoGlass?: boolean; + /** @beta Flag indicating that the drawer panel should use glass styles when in glass theme */ + isGlass?: boolean; + /** @beta Flag indicating that the drawer panel should use plain styles. This only applies when the drawer is static or inline. */ + isPlain?: boolean; + /** @beta Flag indicating that plain styles should be disabled when glass styles are used. This only applies when the drawer is static or inline. */ + isNoPlainOnGlass?: boolean; /** Callback for resize end. */ - onResize?: (width: number, id: string) => void; - /** The minimum size of a drawer, in either pixels or percentage. */ + onResize?: (event: MouseEvent | TouchEvent | React.KeyboardEvent, width: number, id: string) => void; + /** The minimum size of a drawer. */ minSize?: string; - /** The starting size of a resizable drawer, in either pixels or percentage. */ + /** The starting size of a drawer. */ defaultSize?: string; - /** The maximum size of a drawer, in either pixels or percentage. */ + /** The maximum size of a drawer. */ maxSize?: string; - /** The increment amount for keyboard drawer resizing, in pixels. */ + /** The increment amount for keyboard drawer resizing. */ increment?: number; /** Aria label for the resizable drawer splitter. */ resizeAriaLabel?: string; - /** Aria described by label for the resizable drawer splitter. */ - resizeAriaDescribedBy?: string; - /** Width for drawer panel at various breakpoints. Overriden by resizable drawer minSize and defaultSize. */ + /** Width for drawer panel at various breakpoints. Overridden by resizable drawer minSize and defaultSize. */ widths?: { default?: 'width_25' | 'width_33' | 'width_50' | 'width_66' | 'width_75' | 'width_100'; lg?: 'width_25' | 'width_33' | 'width_50' | 'width_66' | 'width_75' | 'width_100'; xl?: 'width_25' | 'width_33' | 'width_50' | 'width_66' | 'width_75' | 'width_100'; '2xl'?: 'width_25' | 'width_33' | 'width_50' | 'width_66' | 'width_75' | 'width_100'; }; - /** Color variant of the background of the drawer panel */ - colorVariant?: DrawerColorVariant | 'light-200' | 'default'; + /** + * Color variant of the background of the drawer panel. + * The `no-background`is deprecated; use the `isPlain` prop instead. + */ + colorVariant?: DrawerColorVariant | 'no-background' | 'default' | 'secondary'; + /** Adds and customizes a focus trap on the drawer panel content. */ + focusTrap?: DrawerPanelFocusTrapObject; } let isResizing: boolean = null; let newSize: number = 0; export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps> = ({ - className = '', + className, id, children, hasNoBorder = false, isResizable = false, + hasNoGlass = false, + isGlass = false, + isPlain = false, + isNoPlainOnGlass = false, onResize, minSize, defaultSize, maxSize, increment = 5, resizeAriaLabel = 'Resize', - resizeAriaDescribedBy = 'Press space to begin resizing, and use the arrow keys to grow or shrink the panel. Press enter or escape to finish resizing.', widths, colorVariant = DrawerColorVariant.default, + focusTrap, + style, ...props }: DrawerPanelContentProps) => { - const panel = React.useRef<HTMLDivElement>(); - const { position, isExpanded, isStatic, onExpand, drawerRef } = React.useContext(DrawerContext); + const panelId = useSSRSafeId('pf-drawer-panel-'); + const panel = useRef<HTMLDivElement>(undefined); + const splitterRef = useRef<HTMLDivElement>(undefined); + const [separatorValue, setSeparatorValue] = useState(0); + const { position, isExpanded, isStatic, onExpand, drawerRef, drawerContentRef, isInline } = useContext(DrawerContext); const hidden = isStatic ? false : !isExpanded; - const [isExpandedInternal, setIsExpandedInternal] = React.useState(!hidden); + const [isExpandedInternal, setIsExpandedInternal] = useState(!hidden); + const [isFocusTrapActive, setIsFocusTrapActive] = useState(false); + const [shouldCollapseSpace, setShouldCollapseSpace] = useState(hidden); + const previouslyFocusedElement = useRef(null); let currWidth: number = 0; let panelRect: DOMRect; - let right: number; - let left: number; + let end: number; + let start: number; let bottom: number; let setInitialVals: boolean = true; - React.useEffect(() => { + if (isStatic && focusTrap?.enabled) { + // eslint-disable-next-line no-console + console.warn( + `DrawerPanelContent: The focusTrap.enabled prop cannot be true if the Drawer's isStatic prop is true. This will cause a permanent focus trap.` + ); + } + + useEffect(() => { if (!isStatic && isExpanded) { setIsExpandedInternal(isExpanded); + setShouldCollapseSpace(false); } }, [isStatic, isExpanded]); + const calcValueNow = () => { + let splitterPos; + let drawerSize; + const isRTL = getLanguageDirection(panel.current) === 'rtl'; + + if (isInline && (position === 'end' || position === 'right')) { + if (isRTL) { + splitterPos = panel.current.getBoundingClientRect().left - splitterRef.current.getBoundingClientRect().right; + drawerSize = drawerRef.current.getBoundingClientRect().left - drawerRef.current.getBoundingClientRect().right; + } else { + splitterPos = panel.current.getBoundingClientRect().right - splitterRef.current.getBoundingClientRect().left; + drawerSize = drawerRef.current.getBoundingClientRect().right - drawerRef.current.getBoundingClientRect().left; + } + } else if (isInline && (position === 'start' || position === 'left')) { + if (isRTL) { + splitterPos = splitterRef.current.getBoundingClientRect().left - panel.current.getBoundingClientRect().right; + drawerSize = drawerRef.current.getBoundingClientRect().left - drawerRef.current.getBoundingClientRect().right; + } else { + splitterPos = splitterRef.current.getBoundingClientRect().right - panel.current.getBoundingClientRect().left; + drawerSize = drawerRef.current.getBoundingClientRect().right - drawerRef.current.getBoundingClientRect().left; + } + } else if (position === 'end' || position === 'right') { + if (isRTL) { + splitterPos = + drawerContentRef.current.getBoundingClientRect().left - splitterRef.current.getBoundingClientRect().right; + drawerSize = + drawerContentRef.current.getBoundingClientRect().left - + drawerContentRef.current.getBoundingClientRect().right; + } else { + splitterPos = + drawerContentRef.current.getBoundingClientRect().right - splitterRef.current.getBoundingClientRect().left; + drawerSize = + drawerContentRef.current.getBoundingClientRect().right - + drawerContentRef.current.getBoundingClientRect().left; + } + } else if (position === 'start' || position === 'left') { + if (isRTL) { + splitterPos = + splitterRef.current.getBoundingClientRect().left - drawerContentRef.current.getBoundingClientRect().right; + drawerSize = + drawerContentRef.current.getBoundingClientRect().left - + drawerContentRef.current.getBoundingClientRect().right; + } else { + splitterPos = + splitterRef.current.getBoundingClientRect().right - drawerContentRef.current.getBoundingClientRect().left; + drawerSize = + drawerContentRef.current.getBoundingClientRect().right - + drawerContentRef.current.getBoundingClientRect().left; + } + } else if (position === 'bottom') { + splitterPos = + drawerContentRef.current.getBoundingClientRect().bottom - splitterRef.current.getBoundingClientRect().top; + drawerSize = + drawerContentRef.current.getBoundingClientRect().bottom - drawerContentRef.current.getBoundingClientRect().top; + } + + const newSplitterPos = (splitterPos / drawerSize) * 100; + return Math.round((newSplitterPos + Number.EPSILON) * 100) / 100; + }; + const handleTouchStart = (e: React.TouchEvent) => { e.stopPropagation(); document.addEventListener('touchmove', callbackTouchMove, { passive: false }); @@ -106,6 +216,8 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps }; const handleControlMove = (e: MouseEvent | TouchEvent, controlPosition: number) => { + const isRTL = getLanguageDirection(panel.current) === 'rtl'; + e.stopPropagation(); if (!isResizing) { return; @@ -113,17 +225,22 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps if (setInitialVals) { panelRect = panel.current.getBoundingClientRect(); - right = panelRect.right; - left = panelRect.left; + if (isRTL) { + start = panelRect.right; + end = panelRect.left; + } else { + end = panelRect.right; + start = panelRect.left; + } bottom = panelRect.bottom; setInitialVals = false; } const mousePos = controlPosition; let newSize = 0; - if (position === 'right') { - newSize = right - mousePos; - } else if (position === 'left') { - newSize = mousePos - left; + if (position === 'end' || position === 'right') { + newSize = isRTL ? mousePos - end : end - mousePos; + } else if (position === 'start' || position === 'left') { + newSize = isRTL ? start - mousePos : mousePos - start; } else { newSize = bottom - mousePos; } @@ -131,17 +248,18 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps if (position === 'bottom') { panel.current.style.overflowAnchor = 'none'; } - panel.current.style.setProperty('--pf-c-drawer__panel--md--FlexBasis', newSize + 'px'); + panel.current.style.setProperty(cssPanelMdFlexBasis.name, newSize + 'px'); currWidth = newSize; + setSeparatorValue(calcValueNow()); }; - const handleMouseup = () => { + const handleMouseup = (e: MouseEvent) => { if (!isResizing) { return; } drawerRef.current.classList.remove(css(styles.modifiers.resizing)); isResizing = false; - onResize && onResize(currWidth, id); + onResize && onResize(e, currWidth, id); setInitialVals = true; document.removeEventListener('mousemove', callbackMouseMove); document.removeEventListener('mouseup', callbackMouseUp); @@ -153,20 +271,21 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps return; } isResizing = false; - onResize && onResize(currWidth, id); + onResize && onResize(e, currWidth, id); document.removeEventListener('touchmove', callbackTouchMove); document.removeEventListener('touchend', callbackTouchEnd); }; - const callbackMouseMove = React.useCallback(handleMouseMove, []); - const callbackTouchEnd = React.useCallback(handleTouchEnd, []); - const callbackTouchMove = React.useCallback(handleTouchMove, []); - const callbackMouseUp = React.useCallback(handleMouseup, []); + const callbackMouseMove = useCallback(handleMouseMove, []); + const callbackTouchEnd = useCallback(handleTouchEnd, []); + const callbackTouchMove = useCallback(handleTouchMove, []); + const callbackMouseUp = useCallback(handleMouseup, []); const handleKeys = (e: React.KeyboardEvent) => { + const isRTL = getLanguageDirection(panel.current) === 'rtl'; + const key = e.key; if ( - key !== ' ' && key !== 'Escape' && key !== 'Enter' && key !== 'ArrowUp' && @@ -181,94 +300,147 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps } e.preventDefault(); - if (key === ' ' || key === 'Escape' || key === 'Enter') { - if (key === ' ') { - isResizing = true; - } else { - isResizing = false; - onResize && onResize(currWidth, id); - } - const panelRect = panel.current.getBoundingClientRect(); - newSize = position === 'bottom' ? panelRect.height : panelRect.width; + if (key === 'Escape' || key === 'Enter') { + onResize && onResize(e, currWidth, id); } - - if (isResizing) { - let delta = 0; - if (key === 'ArrowRight') { - delta = position === 'left' ? increment : -increment; - } else if (key === 'ArrowLeft') { - delta = position === 'left' ? -increment : increment; - } else if (key === 'ArrowUp') { - delta = increment; - } else if (key === 'ArrowDown') { - delta = -increment; + const panelRect = panel.current.getBoundingClientRect(); + newSize = position === 'bottom' ? panelRect.height : panelRect.width; + let delta = 0; + if (key === 'ArrowRight') { + if (isRTL) { + delta = position === 'left' || position === 'start' ? -increment : increment; + } else { + delta = position === 'left' || position === 'start' ? increment : -increment; } - newSize = newSize + delta; - if (position === 'bottom') { - panel.current.style.overflowAnchor = 'none'; + } else if (key === 'ArrowLeft') { + if (isRTL) { + delta = position === 'left' || position === 'start' ? increment : -increment; + } else { + delta = position === 'left' || position === 'start' ? -increment : increment; } - panel.current.style.setProperty('--pf-c-drawer__panel--md--FlexBasis', newSize + 'px'); - currWidth = newSize; + } else if (key === 'ArrowUp') { + delta = increment; + } else if (key === 'ArrowDown') { + delta = -increment; } + newSize = newSize + delta; + if (position === 'bottom') { + panel.current.style.overflowAnchor = 'none'; + } + panel.current.style.setProperty(cssPanelMdFlexBasis.name, newSize + 'px'); + currWidth = newSize; + setSeparatorValue(calcValueNow()); }; const boundaryCssVars: any = {}; if (defaultSize) { - boundaryCssVars['--pf-c-drawer__panel--md--FlexBasis'] = defaultSize; + boundaryCssVars[cssPanelMdFlexBasis.name] = defaultSize; } if (minSize) { - boundaryCssVars['--pf-c-drawer__panel--md--FlexBasis--min'] = minSize; + boundaryCssVars[cssPanelMdFlexBasisMin.name] = minSize; } if (maxSize) { - boundaryCssVars['--pf-c-drawer__panel--md--FlexBasis--max'] = maxSize; + boundaryCssVars[cssPanelMdFlexBasisMax.name] = maxSize; } + + const isValidFocusTrap = focusTrap?.enabled && !isStatic; + const Component = isValidFocusTrap ? FocusTrap : 'div'; + + const focusTrapProps = { + tabIndex: -1, + 'aria-modal': true, + role: 'dialog', + active: isFocusTrapActive, + 'aria-labelledby': focusTrap?.['aria-labelledby'] || id || panelId, + focusTrapOptions: { + fallbackFocus: () => panel.current, + onActivate: () => { + if (previouslyFocusedElement.current !== document.activeElement) { + previouslyFocusedElement.current = document.activeElement; + } + }, + onDeactivate: () => { + previouslyFocusedElement.current && + previouslyFocusedElement.current.focus && + previouslyFocusedElement.current.focus(); + }, + clickOutsideDeactivates: true, + returnFocusOnDeactivate: false, + // FocusTrap's initialFocus can accept false as a value to prevent initial focus. + // We want to prevent this in case false is ever passed in. + initialFocus: focusTrap?.elementToFocusOnExpand || undefined, + escapeDeactivates: false + } + }; + return ( - <div - id={id} + <Component + {...(isValidFocusTrap && focusTrapProps)} + id={id || panelId} className={css( styles.drawerPanel, isResizable && styles.modifiers.resizable, + hasNoGlass && 'pf-m-no-glass', + isGlass && styles.modifiers.glass, + isPlain && styles.modifiers.plain, + isNoPlainOnGlass && styles.modifiers.noPlainOnGlass, hasNoBorder && styles.modifiers.noBorder, formatBreakpointMods(widths, styles), - colorVariant === DrawerColorVariant.light200 && styles.modifiers.light_200, + colorVariant === DrawerColorVariant.noBackground && styles.modifiers.noBackground, + colorVariant === DrawerColorVariant.secondary && styles.modifiers.secondary, className )} - ref={panel} - onTransitionEnd={ev => { - if (!hidden && ev.nativeEvent.propertyName === 'transform') { - onExpand(); + onTransitionEnd={(ev) => { + if ((ev.target as HTMLElement) === panel.current) { + if (!hidden && ev.nativeEvent.propertyName === 'transform') { + onExpand(ev); + } + setIsExpandedInternal(!hidden); + // We also need to collapse the space when the panel is hidden to prevent automation from scrolling to it + if (hidden && ev.nativeEvent.propertyName === 'transform') { + setShouldCollapseSpace(true); + } + if (isValidFocusTrap && ev.nativeEvent.propertyName === 'transform') { + setIsFocusTrapActive((prevIsFocusTrapActive) => !prevIsFocusTrapActive); + } } - setIsExpandedInternal(!hidden); }} hidden={hidden} - {...((defaultSize || minSize || maxSize) && { - style: boundaryCssVars as React.CSSProperties - })} + style={{ + ...((defaultSize || minSize || maxSize) && boundaryCssVars), + ...style + }} + {...(shouldCollapseSpace && { inert: '' })} {...props} + ref={panel} > {isExpandedInternal && ( - <React.Fragment> + <Fragment> {isResizable && ( - <React.Fragment> + <Fragment> <div className={css(styles.drawerSplitter, position !== 'bottom' && styles.modifiers.vertical)} role="separator" tabIndex={0} aria-orientation={position === 'bottom' ? 'horizontal' : 'vertical'} aria-label={resizeAriaLabel} - aria-describedby={resizeAriaDescribedBy} + aria-valuenow={separatorValue} + aria-valuemin={0} + aria-valuemax={100} + aria-controls={id || panelId} onMouseDown={handleMousedown} onKeyDown={handleKeys} onTouchStart={handleTouchStart} + ref={splitterRef} > <div className={css(styles.drawerSplitterHandle)} aria-hidden></div> </div> <div className={css(styles.drawerPanelMain)}>{children}</div> - </React.Fragment> + </Fragment> )} {!isResizable && children} - </React.Fragment> + </Fragment> )} - </div> + </Component> ); }; DrawerPanelContent.displayName = 'DrawerPanelContent'; diff --git a/packages/react-core/src/components/Drawer/DrawerPanelDescription.tsx b/packages/react-core/src/components/Drawer/DrawerPanelDescription.tsx new file mode 100644 index 00000000000..7d044777f8d --- /dev/null +++ b/packages/react-core/src/components/Drawer/DrawerPanelDescription.tsx @@ -0,0 +1,22 @@ +import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; +import { css } from '@patternfly/react-styles'; + +/** Provides a description within the drawer panel. This should typically follow the drawer head. */ + +export interface DrawerPanelDescriptionProps extends React.HTMLProps<HTMLDivElement> { + /** Additional classes added to the drawer description. */ + className?: string; + /** Content to be rendered in the drawer description */ + children: React.ReactNode; +} + +export const DrawerPanelDescription: React.FunctionComponent<DrawerPanelDescriptionProps> = ({ + className, + children, + ...props +}: DrawerPanelDescriptionProps) => ( + <div className={css(styles.drawerDescription, className)} {...props}> + {children} + </div> +); +DrawerPanelDescription.displayName = 'DrawerPanelDescription'; diff --git a/packages/react-core/src/components/Drawer/DrawerSection.tsx b/packages/react-core/src/components/Drawer/DrawerSection.tsx index 1b248cde577..941fa3fa862 100644 --- a/packages/react-core/src/components/Drawer/DrawerSection.tsx +++ b/packages/react-core/src/components/Drawer/DrawerSection.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; import { css } from '@patternfly/react-styles'; import { DrawerColorVariant } from './Drawer'; @@ -8,21 +7,28 @@ export interface DrawerSectionProps extends React.HTMLProps<HTMLDivElement> { className?: string; /** Content to be rendered in the drawer section. */ children?: React.ReactNode; - /** Color variant of the background of the drawer Section */ - colorVariant?: DrawerColorVariant | 'light-200' | 'default'; + /** + * Color variant of the background of the drawer section. + * The `no-background` value is deprecated; use the `isPlain` prop instead. + */ + colorVariant?: DrawerColorVariant | 'no-background' | 'default' | 'secondary'; + /** @beta Flag indicating that the drawer section should use plain styles. */ + isPlain?: boolean; } -export const DrawerSection: React.SFC<DrawerSectionProps> = ({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars +export const DrawerSection: React.FunctionComponent<DrawerSectionProps> = ({ className = '', children, colorVariant = DrawerColorVariant.default, + isPlain = false, ...props }: DrawerSectionProps) => ( <div className={css( styles.drawerSection, - colorVariant === DrawerColorVariant.light200 && styles.modifiers.light_200, + isPlain && styles.modifiers.plain, + colorVariant === DrawerColorVariant.noBackground && styles.modifiers.noBackground, + colorVariant === DrawerColorVariant.secondary && styles.modifiers.secondary, className )} {...props} diff --git a/packages/react-core/src/components/Drawer/__tests__/Drawer.test.tsx b/packages/react-core/src/components/Drawer/__tests__/Drawer.test.tsx index e64e4e65074..14a0f2f6295 100644 --- a/packages/react-core/src/components/Drawer/__tests__/Drawer.test.tsx +++ b/packages/react-core/src/components/Drawer/__tests__/Drawer.test.tsx @@ -1,3 +1,4 @@ +import { createContext } from 'react'; import { Drawer, DrawerActions, @@ -6,11 +7,15 @@ import { DrawerContentBody, DrawerHead, DrawerPanelBody, - DrawerColorVariant, - DrawerPanelContent + DrawerPanelContent, + DrawerColorVariant } from '../'; -import React from 'react'; -import { mount } from 'enzyme'; +import { screen, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { KeyTypes } from '../../../helpers'; +import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; + +jest.mock('../../../helpers/GenerateId/GenerateId'); Object.values([ { isExpanded: true, isInline: false, isStatic: false }, @@ -33,14 +38,14 @@ Object.values([ const drawerContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; test(`Drawer isExpanded = ${isExpanded} and isInline = ${isInline} and isStatic = ${isStatic}`, () => { - const view = mount( + const { asFragment } = render( <Drawer isExpanded={isExpanded}> <DrawerContent panelContent={panelContent}> <DrawerContentBody>{drawerContent}</DrawerContentBody> </DrawerContent> </Drawer> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); }); @@ -59,19 +64,25 @@ test(`Drawer expands from bottom`, () => { const drawerContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - const view = mount( + const { asFragment } = render( <Drawer isExpanded={true} position="bottom"> <DrawerContent panelContent={panelContent}> <DrawerContentBody>{drawerContent}</DrawerContentBody> </DrawerContent> </Drawer> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); test(`Drawer has resizable css and color variants`, () => { const panelContent = ( - <DrawerPanelContent isResizable minSize={'200px'} defaultSize={'300px'} maxSize={'400px'} colorVariant={DrawerColorVariant.light200}> + <DrawerPanelContent + isResizable + minSize={'200px'} + defaultSize={'300px'} + maxSize={'400px'} + colorVariant={DrawerColorVariant.secondary} + > <DrawerHead> <span>drawer-panel</span> <DrawerActions> @@ -84,14 +95,14 @@ test(`Drawer has resizable css and color variants`, () => { const drawerContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - const view = mount( + const { asFragment } = render( <Drawer isExpanded={true} position="left"> <DrawerContent panelContent={panelContent}> <DrawerContentBody>{drawerContent}</DrawerContentBody> </DrawerContent> </Drawer> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); test(`Drawer has resizable callback and id`, () => { @@ -109,12 +120,70 @@ test(`Drawer has resizable callback and id`, () => { const drawerContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - const view = mount( + const { asFragment } = render( <Drawer isExpanded={true} position="left"> <DrawerContent panelContent={panelContent}> <DrawerContentBody>{drawerContent}</DrawerContentBody> </DrawerContent> </Drawer> ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Resizeable DrawerPanelContent can be wrapped in a context without causing an error', async () => { + const TestContext = createContext({}); + + const consoleError = jest.spyOn(console, 'error').mockImplementation(); + + const panelContent = ( + <TestContext.Provider value={{}}> + <DrawerPanelContent isResizable> + <DrawerHead> + <span>drawer-panel</span> + <DrawerActions> + <DrawerCloseButton /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + </TestContext.Provider> + ); + + const user = userEvent.setup(); + + render( + <Drawer isExpanded={true} position="left"> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>Drawer content text</DrawerContentBody> + </DrawerContent> + </Drawer> + ); + + await user.tab(); + await user.keyboard(`{${KeyTypes.ArrowLeft}}`); + + expect(consoleError).not.toHaveBeenCalled(); +}); + +test(`Renders with ${styles.modifiers.pill} class when specified`, () => { + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span>drawer-panel</span> + <DrawerActions> + <DrawerCloseButton /> + </DrawerActions> + </DrawerHead> + <DrawerPanelBody>drawer-panel</DrawerPanelBody> + </DrawerPanelContent> + ); + + render( + <Drawer data-testid="drawer" isExpanded={true} position="left" isPill> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>Drawer content text</DrawerContentBody> + </DrawerContent> + </Drawer> + ); + + expect(screen.getByTestId('drawer')).toHaveClass(styles.modifiers.pill); }); diff --git a/packages/react-core/src/components/Drawer/__tests__/DrawerPanelContent.test.tsx b/packages/react-core/src/components/Drawer/__tests__/DrawerPanelContent.test.tsx new file mode 100644 index 00000000000..ba0b0cec4c4 --- /dev/null +++ b/packages/react-core/src/components/Drawer/__tests__/DrawerPanelContent.test.tsx @@ -0,0 +1,220 @@ +import { render, screen } from '@testing-library/react'; +import { DrawerPanelContent } from '../DrawerPanelContent'; +import { Drawer } from '../Drawer'; +import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; + +test(`Renders with only class ${styles.drawerPanel} by default`, () => { + render( + <Drawer isExpanded> + <DrawerPanelContent>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveClass(styles.drawerPanel, { exact: true }); +}); + +test(`Renders with class ${styles.modifiers.noBackground} when deprecated colorVariant="no-background" is used`, () => { + render( + <Drawer isExpanded> + <DrawerPanelContent colorVariant="no-background">Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveClass(styles.modifiers.noBackground); +}); + +test(`Renders with class ${styles.modifiers.secondary} when colorVariant="secondary"`, () => { + render( + <Drawer isExpanded> + <DrawerPanelContent colorVariant="secondary">Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveClass(styles.modifiers.secondary); +}); + +jest.mock('../../../helpers/GenerateId/GenerateId'); + +jest.mock('../../../helpers/GenerateId/GenerateId'); + +test('Does not render with aria-labelledby by default', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).not.toHaveAccessibleName(); +}); + +test('Renders with aria-labelledby when focusTrap.enabled is true', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent focusTrap={{ enabled: true }}>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveAccessibleName('Drawer panel content'); +}); + +test('Renders with aria-labelledby when id is passed in', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent id="drawer-panel-content" focusTrap={{ enabled: true }}> + Drawer panel content + </DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveAccessibleName('Drawer panel content'); +}); + +test('Renders with custom aria-labelledby', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent focusTrap={{ enabled: true, 'aria-labelledby': 'drawer-panel-title' }}> + <span id="drawer-panel-title">Title</span> + <span>Drawer panel content</span> + </DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content').parentElement).toHaveAccessibleName('Title'); +}); + +test('Does not render with aria-modal="true" by default', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).not.toHaveAttribute('aria-modal'); +}); + +test('Renders with aria-modal="true" when focusTrap.enabled is true', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent focusTrap={{ enabled: true }}>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveAttribute('aria-modal', 'true'); +}); + +test('Does not render with role="dialog" by default', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); +}); + +test('Renders with role="dialog" when focusTrap.enabled is true', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent focusTrap={{ enabled: true }}>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); +}); + +test('Does not render with inert when drawer is expanded', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent data-testid="drawer-content">Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByTestId('drawer-content')).not.toHaveAttribute('inert'); +}); + +test('Renders with inert when drawer is collapsed', () => { + render( + <Drawer> + <DrawerPanelContent data-testid="drawer-content">Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByTestId('drawer-content')).toHaveAttribute('inert'); +}); + +test('Applies style prop as expected', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent style={{ backgroundColor: 'red', padding: '20px' }}>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + const panelContent = screen.getByText('Drawer panel content'); + expect(panelContent).toHaveStyle({ backgroundColor: 'red', padding: '20px' }); +}); + +test('Style prop overrides boundaryCssVars', () => { + render( + <Drawer isExpanded> + <DrawerPanelContent + defaultSize="200px" + minSize="100px" + maxSize="400px" + style={{ + '--pf-v6-c-drawer__panel--md--FlexBasis': '300px', + '--pf-v6-c-drawer__panel--md--FlexBasis--min': '150px', + '--pf-v6-c-drawer__panel--md--FlexBasis--max': '500px' + }} + > + Drawer panel content + </DrawerPanelContent> + </Drawer> + ); + + const panelContent = screen.getByText('Drawer panel content'); + expect(panelContent).toHaveStyle({ + '--pf-v6-c-drawer__panel--md--FlexBasis': '300px', + '--pf-v6-c-drawer__panel--md--FlexBasis--min': '150px', + '--pf-v6-c-drawer__panel--md--FlexBasis--max': '500px' + }); +}); + +test(`Renders with class 'pf-m-no-glass' when hasNoGlass is true`, () => { + render( + <Drawer isExpanded isPill> + <DrawerPanelContent hasNoGlass>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveClass('pf-m-no-glass'); +}); + +test(`Renders with class ${styles.modifiers.glass} when isGlass is true`, () => { + render( + <Drawer isExpanded> + <DrawerPanelContent isGlass>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveClass(styles.modifiers.glass); +}); + +test(`Renders with class ${styles.modifiers.plain} when isPlain is true`, () => { + render( + <Drawer isExpanded> + <DrawerPanelContent isPlain>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveClass(styles.modifiers.plain); +}); + +test(`Renders with class ${styles.modifiers.noPlainOnGlass} when isNoPlainOnGlass is true`, () => { + render( + <Drawer isExpanded> + <DrawerPanelContent isNoPlainOnGlass>Drawer panel content</DrawerPanelContent> + </Drawer> + ); + + expect(screen.getByText('Drawer panel content')).toHaveClass(styles.modifiers.noPlainOnGlass); +}); diff --git a/packages/react-core/src/components/Drawer/__tests__/DrawerPanelDescription.tsx b/packages/react-core/src/components/Drawer/__tests__/DrawerPanelDescription.tsx new file mode 100644 index 00000000000..bee9ac5818c --- /dev/null +++ b/packages/react-core/src/components/Drawer/__tests__/DrawerPanelDescription.tsx @@ -0,0 +1,28 @@ +import { render, screen } from '@testing-library/react'; +import { DrawerPanelDescription } from '../DrawerPanelDescription'; +import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; +import '@testing-library/jest-dom'; + +test(`Renders with only class ${styles.drawerDescription} by default`, () => { + render(<DrawerPanelDescription>description content</DrawerPanelDescription>); + + expect(screen.getByText('description content')).toHaveClass(styles.drawerDescription, { exact: true }); +}); + +test(`Renders with custom class when className is passed`, () => { + render(<DrawerPanelDescription className="test-class">description content</DrawerPanelDescription>); + + expect(screen.getByText('description content')).toHaveClass('test-class'); +}); + +test(`Spreads props`, () => { + render(<DrawerPanelDescription id="test-id">description content</DrawerPanelDescription>); + + expect(screen.getByText('description content')).toHaveAttribute('id', 'test-id'); +}); + +test(`Matches snapshot`, () => { + const { asFragment } = render(<DrawerPanelDescription>description content</DrawerPanelDescription>); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Drawer/__tests__/DrawerSection.test.tsx b/packages/react-core/src/components/Drawer/__tests__/DrawerSection.test.tsx new file mode 100644 index 00000000000..e080cb25a8c --- /dev/null +++ b/packages/react-core/src/components/Drawer/__tests__/DrawerSection.test.tsx @@ -0,0 +1,37 @@ +import { render, screen } from '@testing-library/react'; +import { DrawerColorVariant } from '../Drawer'; +import { DrawerSection } from '../DrawerSection'; +import styles from '@patternfly/react-styles/css/components/Drawer/drawer'; + +test(`Renders with only class ${styles.drawerSection} by default`, () => { + render(<DrawerSection>Section content</DrawerSection>); + + expect(screen.getByText('Section content')).toHaveClass(styles.drawerSection, { exact: true }); +}); + +test(`Applies ${styles.drawerSection} and ${styles.modifiers.plain} when isPlain is true`, () => { + render(<DrawerSection isPlain>Section content</DrawerSection>); + + const section = screen.getByText('Section content'); + expect(section).toHaveClass(styles.drawerSection); + expect(section).toHaveClass(styles.modifiers.plain); +}); + +test(`Does not apply ${styles.modifiers.plain} when isPlain is false`, () => { + render(<DrawerSection isPlain={false}>Section content</DrawerSection>); + + expect(screen.getByText('Section content')).not.toHaveClass(styles.modifiers.plain); +}); + +test(`Applies plain and secondary modifiers together when isPlain and colorVariant are set`, () => { + render( + <DrawerSection isPlain colorVariant={DrawerColorVariant.secondary}> + Section content + </DrawerSection> + ); + + const section = screen.getByText('Section content'); + expect(section).toHaveClass(styles.drawerSection); + expect(section).toHaveClass(styles.modifiers.plain); + expect(section).toHaveClass(styles.modifiers.secondary); +}); diff --git a/packages/react-core/src/components/Drawer/__tests__/Generated/Drawer.test.tsx b/packages/react-core/src/components/Drawer/__tests__/Generated/Drawer.test.tsx deleted file mode 100644 index 70b6bcef684..00000000000 --- a/packages/react-core/src/components/Drawer/__tests__/Generated/Drawer.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Drawer } from '../../Drawer'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Drawer should match snapshot (auto-generated)', () => { - const view = shallow(<Drawer className={"''"} children={<div>ReactNode</div>} isExpanded={false} isInline={false} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerContent.test.tsx b/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerContent.test.tsx index 9f401b3db14..3ce691d8284 100644 --- a/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerContent.test.tsx +++ b/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerContent.test.tsx @@ -1,13 +1,14 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DrawerContent } from '../../DrawerContent'; // any missing imports can usually be resolved by adding them here import {} from '../..'; it('DrawerContent should match snapshot (auto-generated)', () => { - const view = shallow(<DrawerContent className={"''"} children={<div>ReactNode</div>} />); - expect(view).toMatchSnapshot(); + const { asFragment } = render( + <DrawerContent className={"''"} children={<div>ReactNode</div>} panelContent={<div>test</div>} /> + ); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerPanelContent.test.tsx b/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerPanelContent.test.tsx index 2a70f8bc11c..34c66959937 100644 --- a/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerPanelContent.test.tsx +++ b/packages/react-core/src/components/Drawer/__tests__/Generated/DrawerPanelContent.test.tsx @@ -1,13 +1,14 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import { DrawerPanelContent } from '../../DrawerPanelContent'; // any missing imports can usually be resolved by adding them here import {} from '../..'; +jest.mock('../../../../helpers/GenerateId/GenerateId'); + it('DrawerPanelContent should match snapshot (auto-generated)', () => { - const view = shallow(<DrawerPanelContent className={"''"} children={<div>ReactNode</div>} hasNoPadding={false} />); - expect(view).toMatchSnapshot(); + const { asFragment } = render(<DrawerPanelContent className={"''"} children={<div>ReactNode</div>} />); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/Drawer.test.tsx.snap b/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/Drawer.test.tsx.snap deleted file mode 100644 index adb3b555256..00000000000 --- a/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/Drawer.test.tsx.snap +++ /dev/null @@ -1,25 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Drawer should match snapshot (auto-generated) 1`] = ` -<ContextProvider - value={ - Object { - "drawerRef": Object { - "current": undefined, - }, - "isExpanded": false, - "isStatic": false, - "onExpand": [Function], - "position": "right", - } - } -> - <div - className="pf-c-drawer ''" - > - <div> - ReactNode - </div> - </div> -</ContextProvider> -`; diff --git a/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerContent.test.tsx.snap b/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerContent.test.tsx.snap index a6e69b88182..e0d4691a4da 100644 --- a/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerContent.test.tsx.snap +++ b/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerContent.test.tsx.snap @@ -1,13 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DrawerContent should match snapshot (auto-generated) 1`] = ` -<DrawerMain> +<DocumentFragment> <div - className="pf-c-drawer__content ''" + class="pf-v6-c-drawer__main" > + <div + class="pf-v6-c-drawer__content ''" + > + <div> + ReactNode + </div> + </div> <div> - ReactNode + test </div> </div> -</DrawerMain> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerPanelContent.test.tsx.snap b/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerPanelContent.test.tsx.snap index 17ae77bbd41..9c0d67ba622 100644 --- a/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerPanelContent.test.tsx.snap +++ b/packages/react-core/src/components/Drawer/__tests__/Generated/__snapshots__/DrawerPanelContent.test.tsx.snap @@ -1,10 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DrawerPanelContent should match snapshot (auto-generated) 1`] = ` -<div - className="pf-c-drawer__panel ''" - hasNoPadding={false} - hidden={true} - onTransitionEnd={[Function]} -/> +<DocumentFragment> + <div + class="pf-v6-c-drawer__panel ''" + hidden="" + id="pf-drawer-panel-:r0:" + inert="" + /> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/Drawer/__tests__/__snapshots__/Drawer.test.tsx.snap b/packages/react-core/src/components/Drawer/__tests__/__snapshots__/Drawer.test.tsx.snap index fdc42e784ce..55ba3c0a2bc 100644 --- a/packages/react-core/src/components/Drawer/__tests__/__snapshots__/Drawer.test.tsx.snap +++ b/packages/react-core/src/components/Drawer/__tests__/__snapshots__/Drawer.test.tsx.snap @@ -1,1018 +1,536 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Drawer expands from bottom 1`] = ` -<Drawer - isExpanded={true} - position="bottom" -> +<DocumentFragment> <div - className="pf-c-drawer pf-m-expanded pf-m-panel-bottom" + class="pf-v6-c-drawer pf-m-expanded pf-m-panel-bottom" > - <DrawerContent - panelContent={ - <DrawerPanelContent> - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > + <div + class="pf-v6-c-drawer__body" + > + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. + </div> + </div> + <div + class="pf-v6-c-drawer__panel" + id="pf-drawer-panel-:r8:" + > <div - className="pf-c-drawer__main" + class="pf-v6-c-drawer__head" > + <span> + drawer-panel + </span> <div - className="pf-c-drawer__content" + class="pf-v6-c-drawer__actions" > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent> <div - className="pf-c-drawer__panel" - hidden={false} - onTransitionEnd={[Function]} + class="pf-v6-c-drawer__close" > - <DrawerHead> - <DrawerPanelBody - hasNoPadding={false} + <button + aria-label="Close drawer panel" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:r9:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" > - <div - className="pf-c-drawer__body" + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" > - <div - className="pf-c-drawer__head" - > - <span> - drawer-panel - </span> - <DrawerActions> - <div - className="pf-c-drawer__actions" - > - <DrawerCloseButton> - <div - className="pf-c-drawer__close" - > - <Button - aria-label="Close drawer panel" - onClick={[Function]} - variant="plain" - > - <ButtonBase - aria-label="Close drawer panel" - innerRef={null} - onClick={[Function]} - variant="plain" - > - <button - aria-disabled={false} - aria-label="Close drawer panel" - className="pf-c-button pf-m-plain" - data-ouia-component-id="OUIA-Generated-Button-plain-4" - data-ouia-component-type="PF4/Button" - data-ouia-safe={true} - disabled={false} - onClick={[Function]} - role={null} - type="button" - > - <TimesIcon - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 352 512" - width="1em" - > - <path - d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" - /> - </svg> - </TimesIcon> - </button> - </ButtonBase> - </Button> - </div> - </DrawerCloseButton> - </div> - </DrawerActions> - </div> - </div> - </DrawerPanelBody> - </DrawerHead> - <DrawerPanelBody> - <div - className="pf-c-drawer__body" - > - drawer-panel - </div> - </DrawerPanelBody> + <path + d="M17.8 16.2 11.59 10l6.21-6.21c.42-.46.39-1.17-.07-1.59-.43-.4-1.09-.4-1.52 0l-6.2 6.2-6.22-6.19c-.44-.44-1.15-.44-1.59 0-.44.44-.44 1.15 0 1.59l6.2 6.21-6.2 6.2c-.42.46-.39 1.17.07 1.59.43.4 1.09.4 1.52 0L10 11.59l6.2 6.2c.44.44 1.15.44 1.59 0 .44-.45.44-1.16 0-1.6Z" + /> + </svg> + </span> + </button> </div> - </DrawerPanelContent> + </div> </div> - </DrawerMain> - </DrawerContent> + <div + class="pf-v6-c-drawer__body" + > + drawer-panel + </div> + </div> + </div> </div> -</Drawer> +</DocumentFragment> `; exports[`Drawer has resizable callback and id 1`] = ` -<Drawer - isExpanded={true} - position="left" -> +<DocumentFragment> <div - className="pf-c-drawer pf-m-expanded pf-m-panel-left" + class="pf-v6-c-drawer pf-m-expanded pf-m-panel-left" > - <DrawerContent - panelContent={ - <DrawerPanelContent - id="test-id" - isResizable={true} - onResize={[MockFunction]} - > - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > + <div + class="pf-v6-c-drawer__body" + > + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. + </div> + </div> + <div + class="pf-v6-c-drawer__panel pf-m-resizable" + id="test-id" + > <div - className="pf-c-drawer__main" + aria-controls="test-id" + aria-label="Resize" + aria-orientation="vertical" + aria-valuemax="100" + aria-valuemin="0" + aria-valuenow="0" + class="pf-v6-c-drawer__splitter pf-m-vertical" + role="separator" + tabindex="0" > <div - className="pf-c-drawer__content" - > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent - id="test-id" - isResizable={true} - onResize={[MockFunction]} + aria-hidden="true" + class="pf-v6-c-drawer__splitter-handle" + /> + </div> + <div + class="pf-v6-c-drawer__panel-main" + > + <div + class="pf-v6-c-drawer__head" > + <span> + drawer-panel + </span> <div - className="pf-c-drawer__panel pf-m-resizable" - hidden={false} - id="test-id" - onTransitionEnd={[Function]} + class="pf-v6-c-drawer__actions" > <div - aria-describedby="Press space to begin resizing, and use the arrow keys to grow or shrink the panel. Press enter or escape to finish resizing." - aria-label="Resize" - aria-orientation="vertical" - className="pf-c-drawer__splitter pf-m-vertical" - onKeyDown={[Function]} - onMouseDown={[Function]} - onTouchStart={[Function]} - role="separator" - tabIndex={0} + class="pf-v6-c-drawer__close" > - <div - aria-hidden={true} - className="pf-c-drawer__splitter-handle" - /> - </div> - <div - className="pf-c-drawer__panel-main" - > - <DrawerHead> - <DrawerPanelBody - hasNoPadding={false} + <button + aria-label="Close drawer panel" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:rd:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" > - <div - className="pf-c-drawer__body" + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" > - <div - className="pf-c-drawer__head" - > - <span> - drawer-panel - </span> - <DrawerActions> - <div - className="pf-c-drawer__actions" - > - <DrawerCloseButton> - <div - className="pf-c-drawer__close" - > - <Button - aria-label="Close drawer panel" - onClick={[Function]} - variant="plain" - > - <ButtonBase - aria-label="Close drawer panel" - innerRef={null} - onClick={[Function]} - variant="plain" - > - <button - aria-disabled={false} - aria-label="Close drawer panel" - className="pf-c-button pf-m-plain" - data-ouia-component-id="OUIA-Generated-Button-plain-6" - data-ouia-component-type="PF4/Button" - data-ouia-safe={true} - disabled={false} - onClick={[Function]} - role={null} - type="button" - > - <TimesIcon - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 352 512" - width="1em" - > - <path - d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" - /> - </svg> - </TimesIcon> - </button> - </ButtonBase> - </Button> - </div> - </DrawerCloseButton> - </div> - </DrawerActions> - </div> - </div> - </DrawerPanelBody> - </DrawerHead> - <DrawerPanelBody> - <div - className="pf-c-drawer__body" - > - drawer-panel - </div> - </DrawerPanelBody> + <path + d="M17.8 16.2 11.59 10l6.21-6.21c.42-.46.39-1.17-.07-1.59-.43-.4-1.09-.4-1.52 0l-6.2 6.2-6.22-6.19c-.44-.44-1.15-.44-1.59 0-.44.44-.44 1.15 0 1.59l6.2 6.21-6.2 6.2c-.42.46-.39 1.17.07 1.59.43.4 1.09.4 1.52 0L10 11.59l6.2 6.2c.44.44 1.15.44 1.59 0 .44-.45.44-1.16 0-1.6Z" + /> + </svg> + </span> + </button> </div> </div> - </DrawerPanelContent> + </div> + <div + class="pf-v6-c-drawer__body" + > + drawer-panel + </div> </div> - </DrawerMain> - </DrawerContent> + </div> + </div> </div> -</Drawer> +</DocumentFragment> `; exports[`Drawer has resizable css and color variants 1`] = ` -<Drawer - isExpanded={true} - position="left" -> +<DocumentFragment> <div - className="pf-c-drawer pf-m-expanded pf-m-panel-left" + class="pf-v6-c-drawer pf-m-expanded pf-m-panel-left" > - <DrawerContent - panelContent={ - <DrawerPanelContent - colorVariant="light-200" - defaultSize="300px" - isResizable={true} - maxSize="400px" - minSize="200px" - > - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > + <div + class="pf-v6-c-drawer__body" + > + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. + </div> + </div> + <div + class="pf-v6-c-drawer__panel pf-m-resizable pf-m-secondary" + id="pf-drawer-panel-:ra:" + style="--pf-v6-c-drawer__panel--md--FlexBasis: 300px; --pf-v6-c-drawer__panel--md--FlexBasis--min: 200px; --pf-v6-c-drawer__panel--md--FlexBasis--max: 400px;" + > <div - className="pf-c-drawer__main" + aria-controls="pf-drawer-panel-:ra:" + aria-label="Resize" + aria-orientation="vertical" + aria-valuemax="100" + aria-valuemin="0" + aria-valuenow="0" + class="pf-v6-c-drawer__splitter pf-m-vertical" + role="separator" + tabindex="0" > <div - className="pf-c-drawer__content" - > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent - colorVariant="light-200" - defaultSize="300px" - isResizable={true} - maxSize="400px" - minSize="200px" + aria-hidden="true" + class="pf-v6-c-drawer__splitter-handle" + /> + </div> + <div + class="pf-v6-c-drawer__panel-main" + > + <div + class="pf-v6-c-drawer__head" > + <span> + drawer-panel + </span> <div - className="pf-c-drawer__panel pf-m-resizable pf-m-light-200" - hidden={false} - onTransitionEnd={[Function]} - style={ - Object { - "--pf-c-drawer__panel--md--FlexBasis": "300px", - "--pf-c-drawer__panel--md--FlexBasis--max": "400px", - "--pf-c-drawer__panel--md--FlexBasis--min": "200px", - } - } + class="pf-v6-c-drawer__actions" > <div - aria-describedby="Press space to begin resizing, and use the arrow keys to grow or shrink the panel. Press enter or escape to finish resizing." - aria-label="Resize" - aria-orientation="vertical" - className="pf-c-drawer__splitter pf-m-vertical" - onKeyDown={[Function]} - onMouseDown={[Function]} - onTouchStart={[Function]} - role="separator" - tabIndex={0} + class="pf-v6-c-drawer__close" > - <div - aria-hidden={true} - className="pf-c-drawer__splitter-handle" - /> - </div> - <div - className="pf-c-drawer__panel-main" - > - <DrawerHead> - <DrawerPanelBody - hasNoPadding={false} + <button + aria-label="Close drawer panel" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:rb:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" > - <div - className="pf-c-drawer__body" + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" > - <div - className="pf-c-drawer__head" - > - <span> - drawer-panel - </span> - <DrawerActions> - <div - className="pf-c-drawer__actions" - > - <DrawerCloseButton> - <div - className="pf-c-drawer__close" - > - <Button - aria-label="Close drawer panel" - onClick={[Function]} - variant="plain" - > - <ButtonBase - aria-label="Close drawer panel" - innerRef={null} - onClick={[Function]} - variant="plain" - > - <button - aria-disabled={false} - aria-label="Close drawer panel" - className="pf-c-button pf-m-plain" - data-ouia-component-id="OUIA-Generated-Button-plain-5" - data-ouia-component-type="PF4/Button" - data-ouia-safe={true} - disabled={false} - onClick={[Function]} - role={null} - type="button" - > - <TimesIcon - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 352 512" - width="1em" - > - <path - d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" - /> - </svg> - </TimesIcon> - </button> - </ButtonBase> - </Button> - </div> - </DrawerCloseButton> - </div> - </DrawerActions> - </div> - </div> - </DrawerPanelBody> - </DrawerHead> - <DrawerPanelBody> - <div - className="pf-c-drawer__body" - > - drawer-panel - </div> - </DrawerPanelBody> + <path + d="M17.8 16.2 11.59 10l6.21-6.21c.42-.46.39-1.17-.07-1.59-.43-.4-1.09-.4-1.52 0l-6.2 6.2-6.22-6.19c-.44-.44-1.15-.44-1.59 0-.44.44-.44 1.15 0 1.59l6.2 6.21-6.2 6.2c-.42.46-.39 1.17.07 1.59.43.4 1.09.4 1.52 0L10 11.59l6.2 6.2c.44.44 1.15.44 1.59 0 .44-.45.44-1.16 0-1.6Z" + /> + </svg> + </span> + </button> </div> </div> - </DrawerPanelContent> + </div> + <div + class="pf-v6-c-drawer__body" + > + drawer-panel + </div> </div> - </DrawerMain> - </DrawerContent> + </div> + </div> </div> -</Drawer> +</DocumentFragment> `; exports[`Drawer isExpanded = false and isInline = false and isStatic = false 1`] = ` -<Drawer - isExpanded={false} -> +<DocumentFragment> <div - className="pf-c-drawer" + class="pf-v6-c-drawer" > - <DrawerContent - panelContent={ - <DrawerPanelContent> - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > <div - className="pf-c-drawer__main" + class="pf-v6-c-drawer__body" > - <div - className="pf-c-drawer__content" - > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent> - <div - className="pf-c-drawer__panel" - hidden={true} - onTransitionEnd={[Function]} - /> - </DrawerPanelContent> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. </div> - </DrawerMain> - </DrawerContent> + </div> + <div + class="pf-v6-c-drawer__panel" + hidden="" + id="pf-drawer-panel-:r2:" + inert="" + /> + </div> </div> -</Drawer> +</DocumentFragment> `; exports[`Drawer isExpanded = false and isInline = true and isStatic = false 1`] = ` -<Drawer - isExpanded={false} -> +<DocumentFragment> <div - className="pf-c-drawer" + class="pf-v6-c-drawer" > - <DrawerContent - panelContent={ - <DrawerPanelContent> - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > <div - className="pf-c-drawer__main" + class="pf-v6-c-drawer__body" > - <div - className="pf-c-drawer__content" - > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent> - <div - className="pf-c-drawer__panel" - hidden={true} - onTransitionEnd={[Function]} - /> - </DrawerPanelContent> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. </div> - </DrawerMain> - </DrawerContent> + </div> + <div + class="pf-v6-c-drawer__panel" + hidden="" + id="pf-drawer-panel-:r5:" + inert="" + /> + </div> </div> -</Drawer> +</DocumentFragment> `; exports[`Drawer isExpanded = true and isInline = false and isStatic = false 1`] = ` -<Drawer - isExpanded={true} -> +<DocumentFragment> <div - className="pf-c-drawer pf-m-expanded" + class="pf-v6-c-drawer pf-m-expanded" > - <DrawerContent - panelContent={ - <DrawerPanelContent> - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > <div - className="pf-c-drawer__main" + class="pf-v6-c-drawer__body" > + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. + </div> + </div> + <div + class="pf-v6-c-drawer__panel" + id="pf-drawer-panel-:r0:" + > + <div + class="pf-v6-c-drawer__head" + > + <span> + drawer-panel + </span> <div - className="pf-c-drawer__content" + class="pf-v6-c-drawer__actions" > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent> <div - className="pf-c-drawer__panel" - hidden={false} - onTransitionEnd={[Function]} + class="pf-v6-c-drawer__close" > - <DrawerHead> - <DrawerPanelBody - hasNoPadding={false} + <button + aria-label="Close drawer panel" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:r1:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" > - <div - className="pf-c-drawer__body" + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" > - <div - className="pf-c-drawer__head" - > - <span> - drawer-panel - </span> - <DrawerActions> - <div - className="pf-c-drawer__actions" - > - <DrawerCloseButton> - <div - className="pf-c-drawer__close" - > - <Button - aria-label="Close drawer panel" - onClick={[Function]} - variant="plain" - > - <ButtonBase - aria-label="Close drawer panel" - innerRef={null} - onClick={[Function]} - variant="plain" - > - <button - aria-disabled={false} - aria-label="Close drawer panel" - className="pf-c-button pf-m-plain" - data-ouia-component-id="OUIA-Generated-Button-plain-1" - data-ouia-component-type="PF4/Button" - data-ouia-safe={true} - disabled={false} - onClick={[Function]} - role={null} - type="button" - > - <TimesIcon - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 352 512" - width="1em" - > - <path - d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" - /> - </svg> - </TimesIcon> - </button> - </ButtonBase> - </Button> - </div> - </DrawerCloseButton> - </div> - </DrawerActions> - </div> - </div> - </DrawerPanelBody> - </DrawerHead> - <DrawerPanelBody> - <div - className="pf-c-drawer__body" - > - drawer-panel - </div> - </DrawerPanelBody> + <path + d="M17.8 16.2 11.59 10l6.21-6.21c.42-.46.39-1.17-.07-1.59-.43-.4-1.09-.4-1.52 0l-6.2 6.2-6.22-6.19c-.44-.44-1.15-.44-1.59 0-.44.44-.44 1.15 0 1.59l6.2 6.21-6.2 6.2c-.42.46-.39 1.17.07 1.59.43.4 1.09.4 1.52 0L10 11.59l6.2 6.2c.44.44 1.15.44 1.59 0 .44-.45.44-1.16 0-1.6Z" + /> + </svg> + </span> + </button> </div> - </DrawerPanelContent> + </div> </div> - </DrawerMain> - </DrawerContent> + <div + class="pf-v6-c-drawer__body" + > + drawer-panel + </div> + </div> + </div> </div> -</Drawer> +</DocumentFragment> `; exports[`Drawer isExpanded = true and isInline = false and isStatic = true 1`] = ` -<Drawer - isExpanded={true} -> +<DocumentFragment> <div - className="pf-c-drawer pf-m-expanded" + class="pf-v6-c-drawer pf-m-expanded" > - <DrawerContent - panelContent={ - <DrawerPanelContent> - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > <div - className="pf-c-drawer__main" + class="pf-v6-c-drawer__body" > + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. + </div> + </div> + <div + class="pf-v6-c-drawer__panel" + id="pf-drawer-panel-:r6:" + > + <div + class="pf-v6-c-drawer__head" + > + <span> + drawer-panel + </span> <div - className="pf-c-drawer__content" + class="pf-v6-c-drawer__actions" > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent> <div - className="pf-c-drawer__panel" - hidden={false} - onTransitionEnd={[Function]} + class="pf-v6-c-drawer__close" > - <DrawerHead> - <DrawerPanelBody - hasNoPadding={false} + <button + aria-label="Close drawer panel" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:r7:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" > - <div - className="pf-c-drawer__body" + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" > - <div - className="pf-c-drawer__head" - > - <span> - drawer-panel - </span> - <DrawerActions> - <div - className="pf-c-drawer__actions" - > - <DrawerCloseButton> - <div - className="pf-c-drawer__close" - > - <Button - aria-label="Close drawer panel" - onClick={[Function]} - variant="plain" - > - <ButtonBase - aria-label="Close drawer panel" - innerRef={null} - onClick={[Function]} - variant="plain" - > - <button - aria-disabled={false} - aria-label="Close drawer panel" - className="pf-c-button pf-m-plain" - data-ouia-component-id="OUIA-Generated-Button-plain-3" - data-ouia-component-type="PF4/Button" - data-ouia-safe={true} - disabled={false} - onClick={[Function]} - role={null} - type="button" - > - <TimesIcon - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 352 512" - width="1em" - > - <path - d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" - /> - </svg> - </TimesIcon> - </button> - </ButtonBase> - </Button> - </div> - </DrawerCloseButton> - </div> - </DrawerActions> - </div> - </div> - </DrawerPanelBody> - </DrawerHead> - <DrawerPanelBody> - <div - className="pf-c-drawer__body" - > - drawer-panel - </div> - </DrawerPanelBody> + <path + d="M17.8 16.2 11.59 10l6.21-6.21c.42-.46.39-1.17-.07-1.59-.43-.4-1.09-.4-1.52 0l-6.2 6.2-6.22-6.19c-.44-.44-1.15-.44-1.59 0-.44.44-.44 1.15 0 1.59l6.2 6.21-6.2 6.2c-.42.46-.39 1.17.07 1.59.43.4 1.09.4 1.52 0L10 11.59l6.2 6.2c.44.44 1.15.44 1.59 0 .44-.45.44-1.16 0-1.6Z" + /> + </svg> + </span> + </button> </div> - </DrawerPanelContent> + </div> + </div> + <div + class="pf-v6-c-drawer__body" + > + drawer-panel </div> - </DrawerMain> - </DrawerContent> + </div> + </div> </div> -</Drawer> +</DocumentFragment> `; exports[`Drawer isExpanded = true and isInline = true and isStatic = false 1`] = ` -<Drawer - isExpanded={true} -> +<DocumentFragment> <div - className="pf-c-drawer pf-m-expanded" + class="pf-v6-c-drawer pf-m-expanded" > - <DrawerContent - panelContent={ - <DrawerPanelContent> - <DrawerHead> - <span> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton /> - </DrawerActions> - </DrawerHead> - <DrawerPanelBody> - drawer-panel - </DrawerPanelBody> - </DrawerPanelContent> - } + <div + class="pf-v6-c-drawer__main" > - <DrawerMain> + <div + class="pf-v6-c-drawer__content" + > + <div + class="pf-v6-c-drawer__body" + > + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. + </div> + </div> + <div + class="pf-v6-c-drawer__panel" + id="pf-drawer-panel-:r3:" + > <div - className="pf-c-drawer__main" + class="pf-v6-c-drawer__head" > + <span> + drawer-panel + </span> <div - className="pf-c-drawer__content" + class="pf-v6-c-drawer__actions" > - <DrawerContentBody> - <div - className="pf-c-drawer__body" - > - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate. - </div> - </DrawerContentBody> - </div> - <DrawerPanelContent> <div - className="pf-c-drawer__panel" - hidden={false} - onTransitionEnd={[Function]} + class="pf-v6-c-drawer__close" > - <DrawerHead> - <DrawerPanelBody - hasNoPadding={false} + <button + aria-label="Close drawer panel" + class="pf-v6-c-button pf-m-plain" + data-ouia-component-id="OUIA-Generated-Button-plain-:r4:" + data-ouia-component-type="PF6/Button" + data-ouia-safe="true" + type="button" + > + <span + class="pf-v6-c-button__icon" > - <div - className="pf-c-drawer__body" + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 20 20" + width="1em" > - <div - className="pf-c-drawer__head" - > - <span> - drawer-panel - </span> - <DrawerActions> - <div - className="pf-c-drawer__actions" - > - <DrawerCloseButton> - <div - className="pf-c-drawer__close" - > - <Button - aria-label="Close drawer panel" - onClick={[Function]} - variant="plain" - > - <ButtonBase - aria-label="Close drawer panel" - innerRef={null} - onClick={[Function]} - variant="plain" - > - <button - aria-disabled={false} - aria-label="Close drawer panel" - className="pf-c-button pf-m-plain" - data-ouia-component-id="OUIA-Generated-Button-plain-2" - data-ouia-component-type="PF4/Button" - data-ouia-safe={true} - disabled={false} - onClick={[Function]} - role={null} - type="button" - > - <TimesIcon - color="currentColor" - noVerticalAlign={false} - size="sm" - > - <svg - aria-hidden={true} - aria-labelledby={null} - fill="currentColor" - height="1em" - role="img" - style={ - Object { - "verticalAlign": "-0.125em", - } - } - viewBox="0 0 352 512" - width="1em" - > - <path - d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" - /> - </svg> - </TimesIcon> - </button> - </ButtonBase> - </Button> - </div> - </DrawerCloseButton> - </div> - </DrawerActions> - </div> - </div> - </DrawerPanelBody> - </DrawerHead> - <DrawerPanelBody> - <div - className="pf-c-drawer__body" - > - drawer-panel - </div> - </DrawerPanelBody> + <path + d="M17.8 16.2 11.59 10l6.21-6.21c.42-.46.39-1.17-.07-1.59-.43-.4-1.09-.4-1.52 0l-6.2 6.2-6.22-6.19c-.44-.44-1.15-.44-1.59 0-.44.44-.44 1.15 0 1.59l6.2 6.21-6.2 6.2c-.42.46-.39 1.17.07 1.59.43.4 1.09.4 1.52 0L10 11.59l6.2 6.2c.44.44 1.15.44 1.59 0 .44-.45.44-1.16 0-1.6Z" + /> + </svg> + </span> + </button> </div> - </DrawerPanelContent> + </div> + </div> + <div + class="pf-v6-c-drawer__body" + > + drawer-panel </div> - </DrawerMain> - </DrawerContent> + </div> + </div> </div> -</Drawer> +</DocumentFragment> `; diff --git a/packages/react-core/src/components/Drawer/__tests__/__snapshots__/DrawerPanelDescription.tsx.snap b/packages/react-core/src/components/Drawer/__tests__/__snapshots__/DrawerPanelDescription.tsx.snap new file mode 100644 index 00000000000..aeffb63eac3 --- /dev/null +++ b/packages/react-core/src/components/Drawer/__tests__/__snapshots__/DrawerPanelDescription.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches snapshot 1`] = ` +<DocumentFragment> + <div + class="pf-v6-c-drawer__description" + > + description content + </div> +</DocumentFragment> +`; diff --git a/packages/react-core/src/components/Drawer/examples/Drawer.md b/packages/react-core/src/components/Drawer/examples/Drawer.md index d2179ac5800..22d79215fe6 100644 --- a/packages/react-core/src/components/Drawer/examples/Drawer.md +++ b/packages/react-core/src/components/Drawer/examples/Drawer.md @@ -1,1447 +1,158 @@ --- id: Drawer -cssPrefix: pf-c-drawer +cssPrefix: pf-v6-c-drawer propComponents: [ Drawer, + DrawerSection, DrawerContent, - DrawerPanelContent, DrawerContentBody, - DrawerPanelBody, - DrawerSection, + DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, - DrawerColorVariant + DrawerPanelDescription, + DrawerPanelBody, + DrawerPanelFocusTrapObject, ] section: components --- +import { Fragment, useRef, useState } from 'react'; +import accessibility from '@patternfly/react-styles/css/utilities/Accessibility/accessibility'; + ## Examples ### Basic -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class SimpleDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="./DrawerBasic.tsx" + ``` -### Panel on right - -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class SimpleDrawerPanelRight extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +### Panel at end + +```ts file="./DrawerPanelEnd.tsx" + ``` -### Panel on left - -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class SimpleDrawerPanelLeft extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} position="left" onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +### Panel at start + +```ts file="./DrawerPanelStart.tsx" + ``` ### Panel on bottom -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class SimpleDrawerPanelBottom extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <div style={{ height: '400px' }}> - <Drawer isExpanded={isExpanded} position="bottom" onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </div> - </React.Fragment> - ); - } -} +```ts file="./DrawerPanelBottom.tsx" + ``` ### Basic inline -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class SimpleDrawerInlineContent extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} isInline onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="./DrawerBasicInline.tsx" + ``` -### Inline panel on right - -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class DrawerInlineContentPanelRight extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} isInline onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +### Inline panel at end + +```ts file="./DrawerInlinePanelEnd.tsx" + ``` -### Inline panel on left - -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class DrawerInlineContentPanelLeft extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} isInline position="left" onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +### Inline panel at start + +```ts file="./DrawerInlinePanelStart.tsx" + ``` ### Stacked content body elements -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerPanelBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class DrawerStackedContentBodyElements extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <h3 className="pf-c-title pf-m-2xl" tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer title{' '} - </h3> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - drawer-panel - </DrawerHead> - <DrawerPanelBody hasNoPadding>drawer-panel with no padding</DrawerPanelBody> - <DrawerPanelBody>drawer-panel</DrawerPanelBody> - </DrawerPanelContent> - ); - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>content-body</DrawerContentBody> - <DrawerContentBody hasPadding>content-body with padding</DrawerContentBody> - <DrawerContentBody>content-body</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="./DrawerStackedContentBodyElements.tsx" + ``` ### Modified content padding -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class DrawerModifiedContentPadding extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody hasPadding> - <b>Drawer content padding.</b> {drawerContent} - </DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="DrawerModifiedContentPadding.tsx" + ``` ### Modified panel padding -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class DrawerModifiedPanelPadding extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead hasNoPadding> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="DrawerModifiedPanelPadding.tsx" + ``` ### Additional section above drawer content -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - DrawerSection, - Button -} from '@patternfly/react-core'; - -class DrawerWithSection extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerSection>drawer-section</DrawerSection> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="DrawerAdditionalSectionAboveContent.tsx" + ``` ### Static drawer **Note:** For mobile viewports, all drawer variants behave the same way. At the `md` breakpoint, or where `.pf-m-static{-on-[lg, xl, 2xl]}` is applied, the `static drawer` variant’s `close button` is automatically hidden because the drawer panel doesn’t close by design. -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class StaticDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent> - <DrawerHead> - <span>drawer-panel</span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button className="pf-u-hidden-on-md" aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isStatic isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="DrawerStatic.tsx" + ``` ### Breakpoint -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class SimpleDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent widths={{ default: 'width_33' }}> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="DrawerBreakpoint.tsx" + ``` -### Resizable on right - -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class ResizableDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false, - isResizing: false, - panelWidth: 200 - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onResize = (newWidth, id) => { - this.setState( - { - panelWidth: newWidth - }, - () => console.log(`${id} has new width of: ${newWidth}`) - ); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent - isResizable - onResize={this.onResize} - id="right-resize-panel" - defaultSize={'500px'} - minSize={'150px'} - > - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +### Resizable at end + +```ts file="DrawerResizableAtEnd.tsx" + ``` -### Resizable on left - -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class ResizableDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false, - isResizing: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent isResizable defaultSize={'500px'} minSize={'200px'}> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand} position="left"> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +### Resizable at start + +```ts file="DrawerResizableAtStart.tsx" + ``` ### Resizable on bottom -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class ResizableDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false, - isResizing: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent isResizable defaultSize={'200px'} minSize={'100px'}> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <div style={{ height: '400px' }}> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand} position="bottom"> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </div> - </React.Fragment> - ); - } -} +```ts file="DrawerResizableOnBottom.tsx" + ``` ### Resizable on inline -```js -import React from 'react'; -import { - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - Button -} from '@patternfly/react-core'; - -class ResizableDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false, - isResizing: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - } - - render() { - const { isExpanded } = this.state; - const panelContent = ( - <DrawerPanelContent isResizable defaultSize={'500px'} minSize={'150px'}> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand} isInline> - <DrawerContent panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +```ts file="DrawerResizableOnInline.tsx" + ``` -### Panel with light-200 background -```js -import React from 'react'; -import { - Checkbox, - Drawer, - DrawerPanelContent, - DrawerContent, - DrawerContentBody, - DrawerHead, - DrawerActions, - DrawerCloseButton, - DrawerSection, - Button, - DrawerColorVariant -} from '@patternfly/react-core'; - -class LightGrayDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false, - sectionGray: false, - panelGray: true, - contentGray: false - }; - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onClick = () => { - const isExpanded = !this.state.isExpanded; - this.setState({ - isExpanded - }); - }; - - this.onCloseClick = () => { - this.setState({ - isExpanded: false - }); - }; - - this.togglePanelGray = (checked) => { - this.setState({ - panelGray: checked - }) - }; - - this.toggleSectionGray = (checked) => { - this.setState({ - sectionGray: checked - }) - }; - - this.toggleContentGray = (checked) => { - this.setState({ - contentGray: checked - }) - }; - } - - render() { - const { isExpanded, panelGray, sectionGray, contentGray } = this.state; - const panelContent = ( - <DrawerPanelContent colorVariant={panelGray ? DrawerColorVariant.light200 : DrawerColorVariant.default}> - <DrawerHead> - <span tabIndex={isExpanded ? 0 : -1} ref={this.drawerRef}> - drawer-panel - </span> - <DrawerActions> - <DrawerCloseButton onClick={this.onCloseClick} /> - </DrawerActions> - </DrawerHead> - </DrawerPanelContent> - ); - - const drawerContent = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; - - return ( - <React.Fragment> - <Checkbox - label="Gray panel" - isChecked={this.state.panelGray} - onChange={this.togglePanelGray} - aria-label="Gray panel checkbox" - id="toggle-gray-panel" - name="toggle-gray-panel" - /> - <Checkbox - label="Gray content" - isChecked={this.state.contentGray} - onChange={this.toggleContentGray} - aria-label="Gray content checkbox" - id="toggle-gray-content" - name="toggle-gray-content" - /> - <Checkbox - label="Gray section" - isChecked={this.state.sectionGray} - onChange={this.toggleSectionGray} - aria-label="Gray section checkbox" - id="toggle-gray-section" - name="toggle-gray-section" - /> - <br /> - <Button aria-expanded={isExpanded} onClick={this.onClick}> - Toggle drawer - </Button> - <Drawer isExpanded={isExpanded} onExpand={this.onExpand}> - <DrawerSection colorVariant={sectionGray ? DrawerColorVariant.light200 : DrawerColorVariant.default}> - drawer-section - </DrawerSection> - <DrawerContent colorVariant={contentGray ? DrawerColorVariant.light200 : DrawerColorVariant.default} panelContent={panelContent}> - <DrawerContentBody>{drawerContent}</DrawerContentBody> - </DrawerContent> - </Drawer> - </React.Fragment> - ); - } -} +### Panel with secondary background + +```ts file="DrawerSecondaryBackground.tsx" + +``` + +### With focus trap + +When a [focus trap](/accessibility/develop#trapping-focus) is enabled on an element, a user will only be able to interact with the contents of that element until the focus trap is closed or deactivated. + +To enable and customize a focus trap on a drawer panel, apply the `focusTrap` property to the `<DrawerPanelContent>` component. Enabling a focus trap with `focusTrap.enabled` will also automatically place focus on the first focusable element when the drawer panel expands, and return focus to the previously focused element when it collapses. + +To customize which element receives focus when the drawer panel expands, use the `focusTrap.elementToFocusOnExpand` property. + +```ts file="./DrawerFocusTrap.tsx" + +``` + +### Pill + +```ts file="./DrawerBasicPill.tsx" + +``` + +### Pill inline + +```ts file="./DrawerPillInline.tsx" + ``` diff --git a/packages/react-core/src/components/Drawer/examples/DrawerAdditionalSectionAboveContent.tsx b/packages/react-core/src/components/Drawer/examples/DrawerAdditionalSectionAboveContent.tsx new file mode 100644 index 00000000000..64395a8c59d --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerAdditionalSectionAboveContent.tsx @@ -0,0 +1,59 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + DrawerSection, + Button +} from '@patternfly/react-core'; + +export const DrawerAdditionalSectionAboveContent: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + drawer-panel + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand}> + <DrawerSection>drawer-section</DrawerSection> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerBasic.tsx b/packages/react-core/src/components/Drawer/examples/DrawerBasic.tsx new file mode 100644 index 00000000000..803d1d92aab --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerBasic.tsx @@ -0,0 +1,61 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + DrawerPanelBody, + DrawerPanelDescription, + Button +} from '@patternfly/react-core'; + +export const DrawerBasic: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + <DrawerPanelDescription>Drawer panel description</DrawerPanelDescription> + <DrawerPanelBody>Drawer panel body</DrawerPanelBody> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerBasicInline.tsx b/packages/react-core/src/components/Drawer/examples/DrawerBasicInline.tsx new file mode 100644 index 00000000000..2df988d7740 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerBasicInline.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerBasicInline: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} isInline onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerBasicPill.tsx b/packages/react-core/src/components/Drawer/examples/DrawerBasicPill.tsx new file mode 100644 index 00000000000..fdea78cbfe7 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerBasicPill.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerBasicPill: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} isPill onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerBreakpoint.tsx b/packages/react-core/src/components/Drawer/examples/DrawerBreakpoint.tsx new file mode 100644 index 00000000000..0401fa35331 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerBreakpoint.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerBreakpoint: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent widths={{ default: 'width_33' }}> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerFocusTrap.tsx b/packages/react-core/src/components/Drawer/examples/DrawerFocusTrap.tsx new file mode 100644 index 00000000000..5f5f44422e7 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerFocusTrap.tsx @@ -0,0 +1,58 @@ +import { Fragment, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerFocusTrap: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + // An onKeyDown property must be passed to the Drawer component to handle closing + // the drawer panel and deactivating the focus trap via the Escape key. + const onEscape = (event: React.KeyboardEvent) => { + if (event.key === 'Escape') { + setIsExpanded(false); + } + }; + + const panelContent = ( + <DrawerPanelContent focusTrap={{ enabled: true }}> + <DrawerHead> + <span>Drawer panel header</span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer with focus trap + </Button> + <Drawer onKeyDown={onEscape} isExpanded={isExpanded}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerInlinePanelEnd.tsx b/packages/react-core/src/components/Drawer/examples/DrawerInlinePanelEnd.tsx new file mode 100644 index 00000000000..071cd9a3244 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerInlinePanelEnd.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerInlinePanelEnd: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} isInline onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerInlinePanelStart.tsx b/packages/react-core/src/components/Drawer/examples/DrawerInlinePanelStart.tsx new file mode 100644 index 00000000000..ffe46a2b9e1 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerInlinePanelStart.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerInlinePanelStart: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} isInline position="start" onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerModifiedContentPadding.tsx b/packages/react-core/src/components/Drawer/examples/DrawerModifiedContentPadding.tsx new file mode 100644 index 00000000000..9a06d057e3f --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerModifiedContentPadding.tsx @@ -0,0 +1,59 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerModifiedContentPadding: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody hasPadding> + <b>Drawer content padding.</b> {drawerContent} + </DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerModifiedPanelPadding.tsx b/packages/react-core/src/components/Drawer/examples/DrawerModifiedPanelPadding.tsx new file mode 100644 index 00000000000..afabeb0f9df --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerModifiedPanelPadding.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerModifiedPanelPadding: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerPanelBottom.tsx b/packages/react-core/src/components/Drawer/examples/DrawerPanelBottom.tsx new file mode 100644 index 00000000000..1b765555597 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerPanelBottom.tsx @@ -0,0 +1,59 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerPanelBottom: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <div style={{ height: '400px' }}> + <Drawer isExpanded={isExpanded} position="bottom" onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </div> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerPanelEnd.tsx b/packages/react-core/src/components/Drawer/examples/DrawerPanelEnd.tsx new file mode 100644 index 00000000000..6c3460ace2f --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerPanelEnd.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerPanelEnd: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} position="end" onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerPanelStart.tsx b/packages/react-core/src/components/Drawer/examples/DrawerPanelStart.tsx new file mode 100644 index 00000000000..a1acde0be10 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerPanelStart.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerPanelStart: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} position="start" onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerPillInline.tsx b/packages/react-core/src/components/Drawer/examples/DrawerPillInline.tsx new file mode 100644 index 00000000000..16ae9532739 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerPillInline.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerBasicPill: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} isPill isInline onExpand={onExpand}> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerResizableAtEnd.tsx b/packages/react-core/src/components/Drawer/examples/DrawerResizableAtEnd.tsx new file mode 100644 index 00000000000..939fcf4a441 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerResizableAtEnd.tsx @@ -0,0 +1,62 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerResizableAtEnd: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const onResize = (_event: MouseEvent | TouchEvent | React.KeyboardEvent, newWidth: number, id: string) => { + // eslint-disable-next-line no-console + console.log(`${id} has new width of: ${newWidth}`); + }; + + const panelContent = ( + <DrawerPanelContent isResizable onResize={onResize} id="end-resize-panel" defaultSize={'500px'} minSize={'150px'}> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand} position="end"> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerResizableAtStart.tsx b/packages/react-core/src/components/Drawer/examples/DrawerResizableAtStart.tsx new file mode 100644 index 00000000000..32e56665aa0 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerResizableAtStart.tsx @@ -0,0 +1,57 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; + +export const DrawerResizableAtStart: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent isResizable defaultSize={'500px'} minSize={'200px'}> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand} position="start"> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerResizableOnBottom.tsx b/packages/react-core/src/components/Drawer/examples/DrawerResizableOnBottom.tsx new file mode 100644 index 00000000000..ecce2daa1ca --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerResizableOnBottom.tsx @@ -0,0 +1,58 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button, + DrawerContent, + DrawerContentBody +} from '@patternfly/react-core'; + +export const DrawerResizableOnBottom: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + const panelContent = ( + <DrawerPanelContent isResizable defaultSize={'200px'} minSize={'100px'}> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <div style={{ height: '400px' }}> + <Drawer isExpanded={isExpanded} onExpand={onExpand} position="bottom"> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </div> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerResizableOnInline.tsx b/packages/react-core/src/components/Drawer/examples/DrawerResizableOnInline.tsx new file mode 100644 index 00000000000..16299b6db8e --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerResizableOnInline.tsx @@ -0,0 +1,56 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button, + DrawerContent, + DrawerContentBody +} from '@patternfly/react-core'; + +export const DrawerResizableOnInline: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + const panelContent = ( + <DrawerPanelContent isResizable defaultSize={'500px'} minSize={'150px'}> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand} isInline> + <DrawerContent panelContent={panelContent}> + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerSecondaryBackground.tsx b/packages/react-core/src/components/Drawer/examples/DrawerSecondaryBackground.tsx new file mode 100644 index 00000000000..485dff0dcbf --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerSecondaryBackground.tsx @@ -0,0 +1,108 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Checkbox, + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + DrawerSection, + Button, + DrawerColorVariant, + DrawerContentColorVariant +} from '@patternfly/react-core'; + +export const DrawerSecondaryBackground: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const [panelSecondary, setPanelSecondary] = useState(true); + const [contentSecondary, setContentSecondary] = useState(false); + const [sectionSecondary, setSectionSecondary] = useState(false); + + const drawerRef = useRef<HTMLSpanElement>(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const togglePanelSecondary = (checked: boolean) => { + setPanelSecondary(checked); + }; + + const toggleSectionSecondary = (checked: boolean) => { + setSectionSecondary(checked); + }; + + const toggleContentSecondary = (checked: boolean) => { + setContentSecondary(checked); + }; + + const panelContent = ( + <DrawerPanelContent colorVariant={panelSecondary ? DrawerColorVariant.secondary : DrawerColorVariant.default}> + <DrawerHead> + <span tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header + </span> + <DrawerActions> + <DrawerCloseButton onClick={onCloseClick} /> + </DrawerActions> + </DrawerHead> + </DrawerPanelContent> + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + <Fragment> + <Checkbox + label="Secondary panel" + isChecked={panelSecondary} + onChange={(_event, checked) => togglePanelSecondary(checked)} + aria-label="Secondary panel checkbox" + id="toggle-secondary-panel" + name="toggle-secondary-panel" + /> + <Checkbox + label="Secondary content" + isChecked={contentSecondary} + onChange={(_event, checked) => toggleContentSecondary(checked)} + aria-label="Secondary content checkbox" + id="toggle-secondary-content" + name="toggle-secondary-content" + /> + <Checkbox + label="Secondary section" + isChecked={sectionSecondary} + onChange={(_event, checked) => toggleSectionSecondary(checked)} + aria-label="Secondary section checkbox" + id="toggle-secondary-section" + name="toggle-secondary-section" + /> + <br /> + <Button aria-expanded={isExpanded} onClick={onClick}> + Toggle drawer + </Button> + <Drawer isExpanded={isExpanded} onExpand={onExpand}> + <DrawerSection colorVariant={sectionSecondary ? DrawerColorVariant.secondary : DrawerColorVariant.default}> + drawer-section + </DrawerSection> + <DrawerContent + colorVariant={contentSecondary ? DrawerContentColorVariant.secondary : DrawerContentColorVariant.default} + panelContent={panelContent} + > + <DrawerContentBody>{drawerContent}</DrawerContentBody> + </DrawerContent> + </Drawer> + </Fragment> + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerStackedContentBodyElements.tsx b/packages/react-core/src/components/Drawer/examples/DrawerStackedContentBodyElements.tsx new file mode 100644 index 00000000000..c4f55ddb862 --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerStackedContentBodyElements.tsx @@ -0,0 +1,60 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + DrawerPanelBody, + Button, + Title +} from '@patternfly/react-core'; + +export const DrawerStackedContentBodyElements: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef<HTMLDivElement>(undefined); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + <DrawerPanelContent> + <DrawerHead> + <Title headingLevel="h3" size="2xl" tabIndex={isExpanded ? 0 : -1} ref={drawerRef}> + Drawer panel header in a Title + + + + + + Drawer panel body with no padding + Drawer panel body + + ); + + return ( + + + + + content-body + content-body with padding + content-body + + + + ); +}; diff --git a/packages/react-core/src/components/Drawer/examples/DrawerStatic.tsx b/packages/react-core/src/components/Drawer/examples/DrawerStatic.tsx new file mode 100644 index 00000000000..2f5229223cc --- /dev/null +++ b/packages/react-core/src/components/Drawer/examples/DrawerStatic.tsx @@ -0,0 +1,58 @@ +import { Fragment, useRef, useState } from 'react'; +import { + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, + Button +} from '@patternfly/react-core'; +import accessibility from '@patternfly/react-styles/css/utilities/Accessibility/accessibility'; + +export const DrawerStatic: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + const drawerRef = useRef(null); + + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onClick = () => { + setIsExpanded(!isExpanded); + }; + + const onCloseClick = () => { + setIsExpanded(false); + }; + + const panelContent = ( + + + + Drawer panel header + + + + + + + ); + + const drawerContent = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; + + return ( + + + + + {drawerContent} + + + + ); +}; diff --git a/packages/react-core/src/components/Drawer/index.ts b/packages/react-core/src/components/Drawer/index.ts index 75a59456ac8..72e487b3668 100644 --- a/packages/react-core/src/components/Drawer/index.ts +++ b/packages/react-core/src/components/Drawer/index.ts @@ -3,6 +3,7 @@ export * from './DrawerActions'; export * from './DrawerCloseButton'; export * from './DrawerContent'; export * from './DrawerContentBody'; +export * from './DrawerPanelDescription'; export * from './DrawerHead'; export * from './DrawerPanelBody'; export * from './DrawerPanelContent'; diff --git a/packages/react-core/src/components/Dropdown/BadgeToggle.tsx b/packages/react-core/src/components/Dropdown/BadgeToggle.tsx deleted file mode 100644 index 823da6cf89a..00000000000 --- a/packages/react-core/src/components/Dropdown/BadgeToggle.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { DropdownToggleProps } from './DropdownToggle'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; -import { Toggle } from './Toggle'; -import { Badge, BadgeProps } from '../Badge'; - -export interface BadgeToggleProps extends DropdownToggleProps { - /** HTML ID of dropdown toggle */ - id?: string; - /** Anything which can be rendered as dropdown toggle */ - children?: React.ReactNode; - /** Badge specific properties */ - badgeProps?: BadgeProps; - /** Classess applied to root element of dropdown toggle */ - className?: string; - /** Flag to indicate if menu is opened */ - isOpen?: boolean; - /** Label Toggle button */ - 'aria-label'?: string; - /** Callback called when toggle is clicked */ - onToggle?: (isOpen: boolean) => void; - /** Element which wraps toggle */ - parentRef?: any; - /** The menu element */ - getMenuRef?: () => HTMLElement; - /** Forces active state */ - isActive?: boolean; - /** Disables the dropdown toggle */ - isDisabled?: boolean; - /** Display the toggle with no border or background */ - isPlain?: boolean; - /** Type to put on the button */ - type?: 'button' | 'submit' | 'reset'; - /** Allows selecting toggle to select parent */ - bubbleEvent?: boolean; -} - -export const BadgeToggle: React.FunctionComponent = ({ - id = '', - children = null, - badgeProps = { isRead: true }, - className = '', - isOpen = false, - 'aria-label': ariaLabel = 'Actions', - parentRef = null, - getMenuRef = null, - isActive = false, - isPlain = null, - isDisabled = false, - bubbleEvent = false, - onToggle = () => undefined as void, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, // Types of Ref are different for React.FC vs React.Component - ...props -}: BadgeToggleProps) => ( - - - {children} - - - - - -); -BadgeToggle.displayName = 'BadgeToggle'; diff --git a/packages/react-core/src/components/Dropdown/Dropdown.tsx b/packages/react-core/src/components/Dropdown/Dropdown.tsx index 18efadb8906..80219aebdc3 100644 --- a/packages/react-core/src/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/components/Dropdown/Dropdown.tsx @@ -1,85 +1,218 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { DropdownPosition, DropdownDirection, DropdownContext } from './dropdownConstants'; -import { DropdownWithContext } from './DropdownWithContext'; -import { ToggleMenuBaseProps } from '../../helpers/Popper/Popper'; -import { OUIAProps, useOUIAId } from '../../helpers'; - -export interface DropdownProps extends ToggleMenuBaseProps, React.HTMLProps, OUIAProps { - /** Anything which can be rendered in a dropdown */ +import { forwardRef, useEffect, useRef } from 'react'; +import { css } from '@patternfly/react-styles'; +import { Menu, MenuContent, MenuProps } from '../Menu'; +import { Popper, PopperOptions } from '../../helpers/Popper/Popper'; +import type { DropdownItemProps } from './DropdownItem'; +import { useOUIAProps, OUIAProps, onToggleArrowKeydownDefault } from '../../helpers'; + +/** @deprecated Use PopperOptions instead */ +export type DropdownPopperProps = PopperOptions; + +export interface DropdownToggleProps { + /** Dropdown toggle node. */ + toggleNode: React.ReactNode; + /** Reference to the toggle. */ + toggleRef?: React.RefObject; +} + +/** + * See the Menu documentation for additional props that may be passed. + */ +export interface DropdownProps extends MenuProps, OUIAProps { + /** Anything which can be rendered in a dropdown. */ children?: React.ReactNode; - /** Classes applied to root element of dropdown */ + /** Classes applied to root element of dropdown. */ className?: string; - /** Array of DropdownItem nodes that will be rendered in the dropdown Menu list */ - dropdownItems?: any[]; - /** Flag to indicate if menu is opened */ + /** Dropdown toggle. The toggle should either be a renderer function which forwards the given toggle ref, or a direct ReactNode that should be passed along with the toggleRef property. */ + toggle: DropdownToggleProps | ((toggleRef: React.RefObject) => React.ReactNode); + /** Flag to indicate if menu is opened.*/ isOpen?: boolean; - /** Display the toggle with no border or background */ + /** Flag indicating the toggle should be focused after a selection. If this use case is too restrictive, the optional toggleRef property with a node toggle may be used to control focus. */ + shouldFocusToggleOnSelect?: boolean; + /** Function callback called when user selects item. */ + onSelect?: (event?: React.MouseEvent, value?: DropdownItemProps['value']) => void; + /** Callback to allow the dropdown component to change the open state of the menu. + * Triggered by clicking outside of the menu, or by pressing any keys specified in onOpenChangeKeys. */ + onOpenChange?: (isOpen: boolean) => void; + /** Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable. */ + onOpenChangeKeys?: string[]; + /** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */ + onToggleKeydown?: (event: KeyboardEvent) => void; + /** Indicates if the menu should be without the outer box-shadow. */ isPlain?: boolean; - /** Display the toggle in text only mode */ - isText?: boolean; - /** Flag indicating that the dropdown should expand to full height */ - isFullHeight?: boolean; - /** Indicates where menu will be aligned horizontally */ - position?: DropdownPosition | 'right' | 'left'; - /** Indicates how the menu will align at screen size breakpoints. Default alignment is set via the position property. */ - alignments?: { - sm?: 'right' | 'left'; - md?: 'right' | 'left'; - lg?: 'right' | 'left'; - xl?: 'right' | 'left'; - '2xl'?: 'right' | 'left'; - }; - /** Display menu above or below dropdown toggle */ - direction?: DropdownDirection | 'up' | 'down'; - /** Flag to indicate if dropdown has groups */ - isGrouped?: boolean; - /** Toggle for the dropdown, examples: or */ - toggle: React.ReactElement; - /** Function callback called when user selects item */ - onSelect?: (event?: React.SyntheticEvent) => void; - /** Flag to indicate if the first dropdown item should gain initial focus, set false when adding - * a specific auto-focus item (like a current selection) otherwise leave as true - */ - autoFocus?: boolean; - /** Props for extreme customization of dropdown */ - contextProps?: typeof DropdownContext; + /** Indicates if the menu should be scrollable. */ + isScrollable?: boolean; + /** @hide Forwarded ref */ + innerRef?: React.Ref; + /** Value to overwrite the randomly generated data-ouia-component-id.*/ + ouiaId?: number | string; + /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ + ouiaSafe?: boolean; + /** When applied, wraps dropdown in a container with a data-ouia-component-id.*/ + containerOuiaId?: number | string; + /** Set the value of data-ouia-safe for the container when containerOuiaId is applied. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ + containerOuiaSafe?: boolean; + /** Sets the base component to render for the container. Defaults to */ + containerComponent?: React.ReactNode; + /** z-index of the dropdown menu */ + zIndex?: number; + /** Additional properties to pass to the Popper */ + popperProps?: PopperOptions; + /** Height of the dropdown menu */ + menuHeight?: string; + /** Maximum height of dropdown menu */ + maxMenuHeight?: string; + /** @beta Flag indicating the first menu item should be focused after opening the dropdown. */ + shouldFocusFirstItemOnOpen?: boolean; + /** Flag indicating if scroll on focus of the first menu item should occur. */ + shouldPreventScrollOnItemFocus?: boolean; + /** Time in ms to wait before firing the toggles' focus event. Defaults to 0 */ + focusTimeoutDelay?: number; } -export const Dropdown: React.FunctionComponent = ({ +const DropdownBase: React.FunctionComponent = ({ + children, + className, onSelect, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, // Types of Ref are different for React.FC vs React.Component + isOpen, + toggle, + shouldFocusToggleOnSelect = false, + onOpenChange, + onToggleKeydown, + isPlain, + isScrollable, + innerRef, ouiaId, - ouiaSafe, - alignments, - contextProps, + ouiaSafe = true, + zIndex = 9999, + popperProps, + onOpenChangeKeys = ['Escape', 'Tab'], + menuHeight, + maxMenuHeight, + shouldFocusFirstItemOnOpen = false, + shouldPreventScrollOnItemFocus = true, + focusTimeoutDelay = 0, + containerOuiaId, + containerOuiaSafe = true, + containerComponent = 'span', ...props -}: DropdownProps) => ( - onSelect && onSelect(event), - toggleTextClass: styles.dropdownToggleText, - toggleIconClass: styles.dropdownToggleImage, - toggleIndicatorClass: styles.dropdownToggleIcon, - menuClass: styles.dropdownMenu, - itemClass: styles.dropdownMenuItem, - toggleClass: styles.dropdownToggle, - baseClass: styles.dropdown, - baseComponent: 'div', - sectionClass: styles.dropdownGroup, - sectionTitleClass: styles.dropdownGroupTitle, - sectionComponent: 'section', - disabledClass: styles.modifiers.disabled, - plainTextClass: styles.modifiers.text, - ouiaId: useOUIAId(Dropdown.displayName, ouiaId), - ouiaSafe, - ouiaComponentType: Dropdown.displayName, - alignments, - ...contextProps - }} - > - - -); +}: DropdownProps) => { + const localMenuRef = useRef(undefined); + const localToggleRef = useRef(undefined); + const ouiaProps = useOUIAProps(Dropdown.displayName, ouiaId, ouiaSafe); + const ContainerComponent = containerComponent as any; + const containerOuiaProps = useOUIAProps('Dropdown container', containerOuiaId, containerOuiaSafe); + + const menuRef = (innerRef as React.RefObject) || localMenuRef; + const toggleRef = + typeof toggle === 'function' || (typeof toggle !== 'function' && !toggle.toggleRef) + ? localToggleRef + : (toggle?.toggleRef as React.RefObject); + + const prevIsOpen = useRef(isOpen); + useEffect(() => { + // menu was opened, focus on first menu item + if (prevIsOpen.current === false && isOpen === true && shouldFocusFirstItemOnOpen) { + setTimeout(() => { + const firstElement = menuRef?.current?.querySelector( + 'li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])' + ); + firstElement && (firstElement as HTMLElement).focus({ preventScroll: shouldPreventScrollOnItemFocus }); + }, focusTimeoutDelay); + } + + prevIsOpen.current = isOpen; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isOpen]); + + useEffect(() => { + const handleMenuKeys = (event: KeyboardEvent) => { + // Close the menu on tab or escape if onOpenChange is provided + if ( + isOpen && + onOpenChange && + (menuRef.current?.contains(event.target as Node) || toggleRef.current?.contains(event.target as Node)) + ) { + if (onOpenChangeKeys.includes(event.key)) { + onOpenChange(false); + toggleRef.current?.focus(); + } + } + + if (toggleRef.current?.contains(event.target as Node)) { + if (onToggleKeydown) { + onToggleKeydown(event); + } else if (isOpen) { + onToggleArrowKeydownDefault(event, menuRef); + } + } + }; + + const handleClick = (event: MouseEvent) => { + // If the event is not on the toggle and onOpenChange callback is provided, close the menu + if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) { + if (isOpen && !menuRef.current?.contains(event.target as Node)) { + onOpenChange(false); + } + } + }; + + window.addEventListener('keydown', handleMenuKeys); + window.addEventListener('click', handleClick); + + return () => { + window.removeEventListener('keydown', handleMenuKeys); + window.removeEventListener('click', handleClick); + }; + }, [ + isOpen, + menuRef, + toggleRef, + onOpenChange, + onOpenChangeKeys, + onToggleKeydown, + shouldPreventScrollOnItemFocus, + shouldFocusFirstItemOnOpen, + focusTimeoutDelay + ]); + + const scrollable = maxMenuHeight !== undefined || menuHeight !== undefined || isScrollable; + + const menu = ( + { + onSelect && onSelect(event, value); + shouldFocusToggleOnSelect && toggleRef.current?.focus(); + }} + isPlain={isPlain} + isScrollable={scrollable} + {...props} + {...ouiaProps} + > + + {children} + + + ); + + const popper = ( + + ); + + return containerOuiaId ? {popper} : popper; +}; + +export const Dropdown = forwardRef((props: DropdownProps, ref: React.Ref) => ( + +)); Dropdown.displayName = 'Dropdown'; diff --git a/packages/react-core/src/components/Dropdown/DropdownGroup.tsx b/packages/react-core/src/components/Dropdown/DropdownGroup.tsx index f6ca197a297..17aef30c5c2 100644 --- a/packages/react-core/src/components/Dropdown/DropdownGroup.tsx +++ b/packages/react-core/src/components/Dropdown/DropdownGroup.tsx @@ -1,36 +1,27 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; -import { DropdownContext } from './dropdownConstants'; +import { MenuGroupProps, MenuGroup } from '../Menu'; -export interface DropdownGroupProps extends Omit, 'label'> { - /** Checkboxes within group */ - children?: React.ReactNode; - /** Additional classes added to the DropdownGroup control */ +/** + * See the MenuGroup section of the Menu documentation for additional props that may be passed. + */ +export interface DropdownGroupProps extends Omit { + /** Anything which can be rendered in a dropdown group. */ + children: React.ReactNode; + /** Classes applied to root element of dropdown group */ className?: string; - /** Group label */ + /** Label of the dropdown group */ label?: React.ReactNode; } export const DropdownGroup: React.FunctionComponent = ({ - children = null, - className = '', - label = '', + children, + className, + label, + labelHeadingLevel = 'h1', ...props }: DropdownGroupProps) => ( - - {({ sectionClass, sectionTitleClass, sectionComponent }) => { - const SectionComponent = sectionComponent as any; - return ( - - {label && ( -

    - {label} -

    - )} -
      {children}
    -
    - ); - }} -
    + + {children} + ); DropdownGroup.displayName = 'DropdownGroup'; diff --git a/packages/react-core/src/components/Dropdown/DropdownItem.tsx b/packages/react-core/src/components/Dropdown/DropdownItem.tsx index bed67abb646..0c973f45e9e 100644 --- a/packages/react-core/src/components/Dropdown/DropdownItem.tsx +++ b/packages/react-core/src/components/Dropdown/DropdownItem.tsx @@ -1,113 +1,74 @@ -import * as React from 'react'; -import { InternalDropdownItemProps, InternalDropdownItem } from './InternalDropdownItem'; -import { DropdownArrowContext } from './dropdownConstants'; +import { forwardRef } from 'react'; +import { css } from '@patternfly/react-styles'; +import { MenuItemProps, MenuItem } from '../Menu'; +import { TooltipProps } from '../Tooltip'; import { useOUIAProps, OUIAProps } from '../../helpers'; -export interface DropdownItemProps extends InternalDropdownItemProps, OUIAProps { - /** Anything which can be rendered as dropdown item */ +/** + * See the MenuItem section of the Menu documentation for additional props that may be passed. + */ +export interface DropdownItemProps extends Omit, OUIAProps { + /** Anything which can be rendered in a dropdown item */ children?: React.ReactNode; /** Classes applied to root element of dropdown item */ className?: string; - /** Class to be applied to list item */ - listItemClassName?: string; - /** - * A ReactElement to render, or a string to use as the component tag. - * Example: component={Alert} - * Example: component="button" - * If React.isValidElement(component) the className prop will be injected unless styleChildren="false" - */ - component?: React.ReactNode; - /** ID for the component element */ - componentID?: string; - /** Whether to set className on component when React.isValidElement(component) */ - styleChildren?: boolean; - /** Render dropdown item as disabled option */ + /** @hide Forwarded ref */ + innerRef?: React.Ref; + /** Description of the dropdown item */ + description?: React.ReactNode; + /** Render item as disabled option */ isDisabled?: boolean; - /** Render dropdown item as aria-disabled option */ + /** Render item as aria-disabled option */ isAriaDisabled?: boolean; - /** Render dropdown item as non-interactive item */ - isPlainText?: boolean; - /** Forces display of the hover state of the element */ - isHovered?: boolean; - /** Default hyperlink location */ - href?: string; - /** Tooltip to display when hovered over the item */ - tooltip?: React.ReactNode; - /** Additional tooltip props forwarded to the Tooltip component */ - tooltipProps?: any; - /** Additional node to include alongside item within the
  • */ - additionalChild?: React.ReactNode; - /** Custom item rendering that receives the DropdownContext */ - customChild?: React.ReactNode; - /** tabIndex to use, null to unset it */ - tabIndex?: number | null; - /** An image to display within the DropdownItem, appearing before any component children */ - icon?: React.ReactNode; - /** Initial focus on the item when the menu is opened (Note: Only applicable to one of the items) */ - autoFocus?: boolean; - /** A short description of the dropdown item, displayed under the dropdown item content */ - description?: React.ReactNode; + /** Identifies the component in the dropdown onSelect callback */ + value?: any; + /** Callback for item click */ + onClick?: (event?: any) => void; + /** Value to overwrite the randomly generated data-ouia-component-id.*/ + ouiaId?: number | string; + /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ + ouiaSafe?: boolean; + /** Props for adding a tooltip to a menu item */ + tooltipProps?: TooltipProps; } -export const DropdownItem: React.FunctionComponent = ({ +const DropdownItemBase: React.FunctionComponent = ({ children, className, - component = 'a', - isDisabled = false, - isAriaDisabled = false, - isPlainText = false, - isHovered = false, - href, - tooltip, - tooltipProps = {}, - listItemClassName, + description, + isDisabled, + isAriaDisabled, + value, onClick, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, // Types of Ref are different for React.FC vs React.Component - additionalChild, - customChild, - tabIndex = -1, - icon = null, - autoFocus, - description = null, - styleChildren, ouiaId, ouiaSafe, + innerRef, + tooltipProps, ...props }: DropdownItemProps) => { const ouiaProps = useOUIAProps(DropdownItem.displayName, ouiaId, ouiaSafe); return ( - - {context => ( - - {children} - - )} - + + {children} + ); }; +export const DropdownItem = forwardRef( + (props: DropdownItemProps, ref: React.Ref) => ( + + ) +); + DropdownItem.displayName = 'DropdownItem'; diff --git a/packages/react-core/src/components/Dropdown/DropdownList.tsx b/packages/react-core/src/components/Dropdown/DropdownList.tsx new file mode 100644 index 00000000000..8f9b8fac4f0 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/DropdownList.tsx @@ -0,0 +1,20 @@ +import { css } from '@patternfly/react-styles'; +import { MenuListProps, MenuList } from '../Menu'; + +export interface DropdownListProps extends MenuListProps { + /** Anything which can be rendered in a dropdown list */ + children: React.ReactNode; + /** Classes applied to root element of dropdown list */ + className?: string; +} + +export const DropdownList: React.FunctionComponent = ({ + children, + className, + ...props +}: DropdownListProps) => ( + + {children} + +); +DropdownList.displayName = 'DropdownList'; diff --git a/packages/react-core/src/components/Dropdown/DropdownMenu.tsx b/packages/react-core/src/components/Dropdown/DropdownMenu.tsx deleted file mode 100644 index 89e049ddae2..00000000000 --- a/packages/react-core/src/components/Dropdown/DropdownMenu.tsx +++ /dev/null @@ -1,263 +0,0 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { css } from '@patternfly/react-styles'; -import { keyHandler, formatBreakpointMods } from '../../helpers/util'; -import { DropdownPosition, DropdownArrowContext, DropdownContext } from './dropdownConstants'; - -export interface DropdownMenuProps { - /** Anything which can be rendered as dropdown items */ - children?: React.ReactNode; - /** Classess applied to root element of dropdown menu */ - className?: string; - /** Flag to indicate if menu is opened */ - isOpen?: boolean; - /** @deprecated - no longer used */ - openedOnEnter?: boolean; - /** Flag to indicate if the first dropdown item should gain initial focus, set false when adding - * a specific auto-focus item (like a current selection) otherwise leave as true - */ - autoFocus?: boolean; - /** Indicates which component will be used as dropdown menu */ - component?: React.ReactNode; - /** Indicates where menu will be alligned horizontally */ - position?: DropdownPosition | 'right' | 'left'; - /** Indicates how the menu will align at screen size breakpoints */ - alignments?: { - sm?: 'right' | 'left'; - md?: 'right' | 'left'; - lg?: 'right' | 'left'; - xl?: 'right' | 'left'; - '2xl'?: 'right' | 'left'; - }; - /** Flag to indicate if menu is grouped */ - isGrouped?: boolean; - // Function to call on component mount - setMenuComponentRef?: any; -} - -export interface DropdownMenuItem extends React.HTMLAttributes { - isDisabled: boolean; - disabled: boolean; - isHovered: boolean; - ref: HTMLElement; -} - -export class DropdownMenu extends React.Component { - static displayName = 'DropdownMenu'; - refsCollection = [] as HTMLElement[][]; - - static defaultProps: DropdownMenuProps = { - className: '', - isOpen: true, - openedOnEnter: false, - autoFocus: true, - position: DropdownPosition.left, - component: 'ul', - isGrouped: false, - setMenuComponentRef: null - }; - - componentDidMount() { - document.addEventListener('keydown', this.onKeyDown); - const { autoFocus } = this.props; - - if (autoFocus) { - // Focus first non-disabled element - const focusTargetCollection = this.refsCollection.find(ref => ref && ref[0] && !ref[0].hasAttribute('disabled')); - const focusTarget = focusTargetCollection && focusTargetCollection[0]; - if (focusTarget && focusTarget.focus) { - setTimeout(() => focusTarget.focus()); - } - } - } - - componentWillUnmount = () => { - document.removeEventListener('keydown', this.onKeyDown); - }; - - static validToggleClasses = [styles.dropdownToggle, styles.dropdownToggleButton] as string[]; - static focusFirstRef = (refCollection: HTMLElement[]) => { - if (refCollection && refCollection[0] && refCollection[0].focus) { - setTimeout(() => refCollection[0].focus()); - } - }; - - onKeyDown = (event: any) => { - if ( - !this.props.isOpen || - !Array.from(document.activeElement.classList).find(className => - DropdownMenu.validToggleClasses.concat(this.context.toggleClass).includes(className) - ) - ) { - return; - } - const refs = this.refsCollection; - if (event.key === 'ArrowDown') { - const firstFocusTargetCollection = refs.find(ref => ref && ref[0] && !ref[0].hasAttribute('disabled')); - DropdownMenu.focusFirstRef(firstFocusTargetCollection); - event.stopPropagation(); - } else if (event.key === 'ArrowUp') { - const collectionLength = refs.length; - const lastFocusTargetCollection = refs.slice(collectionLength - 1, collectionLength); - const lastFocusTarget = lastFocusTargetCollection && lastFocusTargetCollection[0]; - DropdownMenu.focusFirstRef(lastFocusTarget); - event.stopPropagation(); - } - }; - - shouldComponentUpdate() { - // reset refsCollection before updating to account for child removal between mounts - this.refsCollection = [] as HTMLElement[][]; - return true; - } - - childKeyHandler = (index: number, innerIndex: number, position: string, custom = false) => { - keyHandler( - index, - innerIndex, - position, - this.refsCollection, - this.props.isGrouped ? this.refsCollection : React.Children.toArray(this.props.children), - custom - ); - }; - - sendRef = (index: number, nodes: any[], isDisabled: boolean, isSeparator: boolean) => { - this.refsCollection[index] = []; - nodes.map((node, innerIndex) => { - if (!node) { - this.refsCollection[index][innerIndex] = null; - } else if (!node.getAttribute) { - // eslint-disable-next-line react/no-find-dom-node - this.refsCollection[index][innerIndex] = ReactDOM.findDOMNode(node) as HTMLElement; - } else if (isSeparator) { - this.refsCollection[index][innerIndex] = null; - } else { - this.refsCollection[index][innerIndex] = node; - } - }); - }; - - extendChildren() { - const { children, isGrouped } = this.props; - if (isGrouped) { - let index = 0; - return React.Children.map(children, groupedChildren => { - const group = groupedChildren as React.ReactElement; - const props: { children?: React.ReactNode } = {}; - if (group.props && group.props.children) { - if (Array.isArray(group.props.children)) { - props.children = React.Children.map(group.props.children, option => - React.cloneElement(option as React.ReactElement, { - index: index++ - }) - ); - } else { - props.children = React.cloneElement(group.props.children as React.ReactElement, { - index: index++ - }); - } - } - return React.cloneElement(group, props); - }); - } - return React.Children.map(children, (child, index) => - React.cloneElement(child as React.ReactElement, { - index - }) - ); - } - - render() { - const { - className, - isOpen, - position, - children, - component, - isGrouped, - setMenuComponentRef, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - openedOnEnter, - alignments, - ...props - } = this.props; - return ( - - {component === 'div' ? ( - - {({ onSelect, menuClass }) => ( - - )} - - ) : ( - (isGrouped && ( - - {({ menuClass, menuComponent }) => { - const MenuComponent = (menuComponent || 'div') as any; - return ( - - ); - }} - - )) || ( - - {({ menuClass, menuComponent }) => { - const MenuComponent = (menuComponent || component) as any; - return ( - - ); - }} - - ) - )} - - ); - } -} - -DropdownMenu.contextType = DropdownContext; diff --git a/packages/react-core/src/components/Dropdown/DropdownSeparator.tsx b/packages/react-core/src/components/Dropdown/DropdownSeparator.tsx deleted file mode 100644 index c026a706199..00000000000 --- a/packages/react-core/src/components/Dropdown/DropdownSeparator.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from 'react'; -import { DropdownArrowContext } from './dropdownConstants'; -import { InternalDropdownItem } from './InternalDropdownItem'; -import { Divider, DividerVariant } from '../Divider'; -import { useOUIAProps, OUIAProps } from '../../helpers'; - -export interface SeparatorProps extends React.HTMLProps, OUIAProps { - /** Classes applied to root element of dropdown item */ - className?: string; - /** Click event to pass to InternalDropdownItem */ - onClick?: (event: React.MouseEvent | React.KeyboardEvent | MouseEvent) => void; -} - -export const DropdownSeparator: React.FunctionComponent = ({ - className = '', - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, // Types of Ref are different for React.FC vs React.Component - ouiaId, - ouiaSafe, - ...props -}: SeparatorProps) => { - const ouiaProps = useOUIAProps(DropdownSeparator.displayName, ouiaId, ouiaSafe); - return ( - - {context => ( - } - className={className} - role="separator" - {...ouiaProps} - /> - )} - - ); -}; -DropdownSeparator.displayName = 'DropdownSeparator'; diff --git a/packages/react-core/src/components/Dropdown/DropdownToggle.tsx b/packages/react-core/src/components/Dropdown/DropdownToggle.tsx deleted file mode 100644 index b3f9987c5dc..00000000000 --- a/packages/react-core/src/components/Dropdown/DropdownToggle.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import * as React from 'react'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; -import { Toggle } from './Toggle'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { DropdownContext } from './dropdownConstants'; -import { css } from '@patternfly/react-styles'; -import { useOUIAProps, OUIAProps } from '../../helpers'; - -export interface DropdownToggleProps extends React.HTMLProps, OUIAProps { - /** HTML ID of dropdown toggle */ - id?: string; - /** Anything which can be rendered as dropdown toggle button */ - children?: React.ReactNode; - /** Classes applied to root element of dropdown toggle button */ - className?: string; - /** Flag to indicate if menu is opened */ - isOpen?: boolean; - /** Callback called when toggle is clicked */ - onToggle?: (value: boolean, event: any) => void; - /** Element which wraps toggle */ - parentRef?: HTMLElement; - /** The menu element */ - getMenuRef?: () => HTMLElement; - /** Forces active state */ - isActive?: boolean; - /** Display the toggle with no border or background */ - isPlain?: boolean; - /** Display the toggle in text only mode */ - isText?: boolean; - /** Whether or not the
    has a disabled state */ - isDisabled?: boolean; - /** @deprecated Use `toggleVariant` instead. Whether or not the dropdown toggle button should have primary button styling */ - isPrimary?: boolean; - /** Alternate styles for the dropdown toggle button */ - toggleVariant?: 'primary' | 'secondary' | 'default'; - /** An image to display within the dropdown toggle, appearing before any component children */ - icon?: React.ReactNode; - /** The icon to display for the toggle, appearing after any component children. Defaults to CaretDownIcon. Set to null to not show an icon. */ - toggleIndicator?: React.ElementType | null; - /** Elements to display before the toggle button. When included, renders the toggle as a split button. */ - splitButtonItems?: React.ReactNode[]; - /** Variant of split button toggle */ - splitButtonVariant?: 'action' | 'checkbox'; - /** Accessible label for the dropdown toggle button */ - 'aria-label'?: string; - /** Accessibility property to indicate correct has popup */ - 'aria-haspopup'?: boolean | 'listbox' | 'menu' | 'dialog' | 'grid' | 'tree'; - /** Type to put on the button */ - type?: 'button' | 'submit' | 'reset'; - /** Callback called when the Enter key is pressed */ - onEnter?: (event?: React.MouseEvent) => void; -} - -export const DropdownToggle: React.FunctionComponent = ({ - id = '', - children = null, - className = '', - isOpen = false, - parentRef = null, - getMenuRef = null, - isDisabled = false, - isPlain = false, - isText = false, - isPrimary = false, - toggleVariant = 'default', - // eslint-disable-next-line @typescript-eslint/no-unused-vars - isActive = false, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onToggle = (_isOpen: boolean) => undefined as any, - icon = null, - toggleIndicator: ToggleIndicator = CaretDownIcon, - splitButtonItems, - splitButtonVariant = 'checkbox', - 'aria-haspopup': ariaHasPopup, - ouiaId, - ouiaSafe, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, // Types of Ref are different for React.FC vs React.Component - ...props -}: DropdownToggleProps) => { - const ouiaProps = useOUIAProps(DropdownToggle.displayName, ouiaId, ouiaSafe); - const toggle = ( - - {({ toggleTextClass, toggleIndicatorClass, toggleIconClass }) => ( - - {icon && {icon}} - {children && {children}} - {ToggleIndicator && ( - - - - )} - - )} - - ); - - if (splitButtonItems) { - return ( -
    - {splitButtonItems} - {toggle} -
    - ); - } - - return toggle; -}; -DropdownToggle.displayName = 'DropdownToggle'; diff --git a/packages/react-core/src/components/Dropdown/DropdownToggleAction.tsx b/packages/react-core/src/components/Dropdown/DropdownToggleAction.tsx deleted file mode 100644 index 24370cf6783..00000000000 --- a/packages/react-core/src/components/Dropdown/DropdownToggleAction.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { css } from '@patternfly/react-styles'; - -export interface DropdownToggleActionProps { - /** Additional classes added to the DropdownToggleAction */ - className?: string; - /** Flag to show if the action button is disabled */ - isDisabled?: boolean; - /** A callback for when the action button is clicked */ - onClick?: (event: React.MouseEvent) => void; - /** Element to be rendered inside the - ); - } -} diff --git a/packages/react-core/src/components/Dropdown/DropdownToggleCheckbox.tsx b/packages/react-core/src/components/Dropdown/DropdownToggleCheckbox.tsx deleted file mode 100644 index e014eee7da4..00000000000 --- a/packages/react-core/src/components/Dropdown/DropdownToggleCheckbox.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { css } from '@patternfly/react-styles'; -import { PickOptional } from '../../helpers/typeUtils'; -import { getOUIAProps, OUIAProps, getDefaultOUIAId } from '../../helpers'; - -export interface DropdownToggleCheckboxProps - extends Omit, 'type' | 'onChange' | 'disabled' | 'checked'>, - OUIAProps { - /** Additional classes added to the DropdownToggleCheckbox */ - className?: string; - /** Flag to show if the checkbox selection is valid or invalid */ - isValid?: boolean; - /** Flag to show if the checkbox is disabled */ - isDisabled?: boolean; - /** Flag to show if the checkbox is checked */ - isChecked?: boolean | null; - /** Alternate Flag to show if the checkbox is checked */ - checked?: boolean | null; - /** A callback for when the checkbox selection changes */ - onChange?: (checked: boolean, event: React.FormEvent) => void; - /** Element to be rendered inside the */ - children?: React.ReactNode; - /** Id of the checkbox */ - id: string; - /** Aria-label of the checkbox */ - 'aria-label': string; -} - -export class DropdownToggleCheckbox extends React.Component { - static displayName = 'DropdownToggleCheckbox'; - static defaultProps: PickOptional = { - className: '', - isValid: true, - isDisabled: false, - onChange: () => undefined as any - }; - - constructor(props: DropdownToggleCheckboxProps) { - super(props); - this.state = { - ouiaStateId: getDefaultOUIAId(DropdownToggleCheckbox.displayName) - }; - } - - handleChange = (event: React.FormEvent) => { - this.props.onChange((event.target as HTMLInputElement).checked, event); - }; - - calculateChecked = () => { - const { isChecked, checked } = this.props; - if (isChecked === null) { - // return false here and the indeterminate state will be set to true through the ref - return false; - } else if (isChecked !== undefined) { - return isChecked; - } - return checked; - }; - - render() { - const { - className, - isValid, - isDisabled, - isChecked, - children, - ouiaId, - ouiaSafe, - /* eslint-disable @typescript-eslint/no-unused-vars */ - onChange, - checked, - /* eslint-enable @typescript-eslint/no-unused-vars */ - ...props - } = this.props; - const text = children && ( - - ); - return ( - - ); - } -} diff --git a/packages/react-core/src/components/Dropdown/DropdownWithContext.tsx b/packages/react-core/src/components/Dropdown/DropdownWithContext.tsx deleted file mode 100644 index 3d4dab86c8c..00000000000 --- a/packages/react-core/src/components/Dropdown/DropdownWithContext.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { css } from '@patternfly/react-styles'; -import { DropdownMenu } from './DropdownMenu'; -import { DropdownProps } from './Dropdown'; -import { DropdownContext, DropdownDirection, DropdownPosition } from './dropdownConstants'; -import { getOUIAProps, OUIAProps } from '../../helpers'; -import { PickOptional } from '../../helpers/typeUtils'; -import { Popper } from '../../helpers/Popper/Popper'; - -export class DropdownWithContext extends React.Component { - static displayName = 'DropdownWithContext'; - - openedOnEnter = false; - baseComponentRef = React.createRef(); - menuComponentRef = React.createRef(); - - // seed for the aria-labelledby ID - static currentId = 0; - - static defaultProps: PickOptional = { - className: '', - dropdownItems: [] as any[], - isOpen: false, - isPlain: false, - isText: false, - isGrouped: false, - position: DropdownPosition.left, - direction: DropdownDirection.down, - onSelect: (): void => undefined, - autoFocus: true, - menuAppendTo: 'inline' - }; - - constructor(props: DropdownProps & OUIAProps) { - super(props); - if (props.dropdownItems && props.dropdownItems.length > 0 && props.children) { - // eslint-disable-next-line no-console - console.error( - 'Children and dropdownItems props have been provided. Only the dropdownItems prop items will be rendered' - ); - } - } - - onEnter = () => { - this.openedOnEnter = true; - }; - - componentDidUpdate() { - if (!this.props.isOpen) { - this.openedOnEnter = false; - } - } - - setMenuComponentRef = (element: any) => { - this.menuComponentRef = element; - }; - - getMenuComponentRef = () => this.menuComponentRef; - - render() { - const { - children, - className, - direction, - dropdownItems, - isOpen, - isPlain, - isText, - isGrouped, - isFullHeight, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onSelect, - position, - toggle, - autoFocus, - menuAppendTo, - ...props - } = this.props; - const id = toggle.props.id || `pf-dropdown-toggle-id-${DropdownWithContext.currentId++}`; - let component: string; - let renderedContent: React.ReactNode[]; - let ariaHasPopup = false; - if (dropdownItems && dropdownItems.length > 0) { - component = 'ul'; - renderedContent = dropdownItems; - ariaHasPopup = true; - } else { - component = 'div'; - renderedContent = React.Children.toArray(children); - } - const openedOnEnter = this.openedOnEnter; - return ( - - {({ baseClass, baseComponent, id: contextId, ouiaId, ouiaComponentType, ouiaSafe, alignments }) => { - const BaseComponent = baseComponent as any; - const menuContainer = ( - - {renderedContent} - - ); - const popperContainer = ( -
    - {isOpen && menuContainer} -
    - ); - const mainContainer = ( - - {React.Children.map(toggle, oneToggle => - React.cloneElement(oneToggle, { - parentRef: this.baseComponentRef, - getMenuRef: this.getMenuComponentRef, - isOpen, - id, - isPlain, - isText, - 'aria-haspopup': ariaHasPopup, - onEnter: () => { - this.onEnter(); - oneToggle.props.onEnter && oneToggle.props.onEnter(); - } - }) - )} - {menuAppendTo === 'inline' && isOpen && menuContainer} - - ); - const getParentElement = () => { - if (this.baseComponentRef && this.baseComponentRef.current) { - return this.baseComponentRef.current.parentElement; - } - return null; - }; - return menuAppendTo === 'inline' ? ( - mainContainer - ) : ( - - ); - }} -
    - ); - } -} diff --git a/packages/react-core/src/components/Dropdown/InternalDropdownItem.tsx b/packages/react-core/src/components/Dropdown/InternalDropdownItem.tsx deleted file mode 100644 index d7c14bb908b..00000000000 --- a/packages/react-core/src/components/Dropdown/InternalDropdownItem.tsx +++ /dev/null @@ -1,293 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import { DropdownContext } from './dropdownConstants'; -import { KEYHANDLER_DIRECTION } from '../../helpers/constants'; -import { preventedEvents } from '../../helpers/util'; -import { Tooltip } from '../Tooltip'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; - -export interface InternalDropdownItemProps extends React.HTMLProps { - /** Anything which can be rendered as dropdown item */ - children?: React.ReactNode; - /** Whether to set className on component when React.isValidElement(component) */ - styleChildren?: boolean; - /** Classes applied to root element of dropdown item */ - className?: string; - /** Class applied to list element */ - listItemClassName?: string; - /** Indicates which component will be used as dropdown item. Will have className injected if React.isValidElement(component) */ - component?: React.ReactNode; - /** Role for the item */ - role?: string; - /** Render dropdown item as disabled option */ - isDisabled?: boolean; - /** Render dropdown item as aria disabled option */ - isAriaDisabled?: boolean; - /** Render dropdown item as a non-interactive item */ - isPlainText?: boolean; - /** Forces display of the hover state of the element */ - isHovered?: boolean; - /** Default hyperlink location */ - href?: string; - /** Tooltip to display when hovered over the item */ - tooltip?: React.ReactNode; - /** Additional tooltip props forwarded to the Tooltip component */ - tooltipProps?: any; - index?: number; - context?: { - keyHandler?: (index: number, innerIndex: number, direction: string) => void; - sendRef?: (index: number, ref: any, isDisabled: boolean, isSeparator: boolean) => void; - }; - /** Callback for click event */ - onClick?: (event: React.MouseEvent | React.KeyboardEvent | MouseEvent) => void; - /** ID for the list element */ - id?: string; - /** ID for the component element */ - componentID?: string; - /** Additional content to include alongside item within the
  • */ - additionalChild?: React.ReactNode; - /** Custom item rendering that receives the DropdownContext */ - customChild?: React.ReactNode; - /** Flag indicating if hitting enter on an item also triggers an arrow down key press */ - enterTriggersArrowDown?: boolean; - /** An image to display within the InternalDropdownItem, appearing before any component children */ - icon?: React.ReactNode; - /** Initial focus on the item when the menu is opened (Note: Only applicable to one of the items) */ - autoFocus?: boolean; - /** A short description of the dropdown item, displayed under the dropdown item content */ - description?: React.ReactNode; - /** Events to prevent when the item is disabled */ - inoperableEvents?: string[]; -} - -export class InternalDropdownItem extends React.Component { - static displayName = 'InternalDropdownItem'; - ref = React.createRef(); - additionalRef = React.createRef(); - - static defaultProps: InternalDropdownItemProps = { - className: '', - isHovered: false, - component: 'a', - role: 'none', - isDisabled: false, - isPlainText: false, - tooltipProps: {}, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onClick: (event: React.MouseEvent | React.KeyboardEvent | MouseEvent) => undefined as any, - index: -1, - context: { - keyHandler: () => {}, - sendRef: () => {} - }, - enterTriggersArrowDown: false, - icon: null, - styleChildren: true, - description: null, - inoperableEvents: ['onClick', 'onKeyPress'] - }; - - componentDidMount() { - const { context, index, isDisabled, role, customChild, autoFocus } = this.props; - const customRef = customChild ? this.getInnerNode(this.ref.current) : this.ref.current; - context.sendRef( - index, - [customRef, customChild ? customRef : this.additionalRef.current], - isDisabled, - role === 'separator' - ); - autoFocus && setTimeout(() => customRef.focus()); - } - - componentDidUpdate() { - const { context, index, isDisabled, role, customChild } = this.props; - const customRef = customChild ? this.getInnerNode(this.ref.current) : this.ref.current; - context.sendRef( - index, - [customRef, customChild ? customRef : this.additionalRef.current], - isDisabled, - role === 'separator' - ); - } - - getInnerNode = (node: any) => (node && node.childNodes && node.childNodes.length ? node.childNodes[0] : node); - - onKeyDown = (event: any) => { - // Detected key press on this item, notify the menu parent so that the appropriate item can be focused - const innerIndex = event.target === this.ref.current ? 0 : 1; - if (!this.props.customChild) { - event.preventDefault(); - } - if (event.key === 'ArrowUp') { - this.props.context.keyHandler(this.props.index, innerIndex, KEYHANDLER_DIRECTION.UP); - event.stopPropagation(); - } else if (event.key === 'ArrowDown') { - this.props.context.keyHandler(this.props.index, innerIndex, KEYHANDLER_DIRECTION.DOWN); - event.stopPropagation(); - } else if (event.key === 'ArrowRight') { - this.props.context.keyHandler(this.props.index, innerIndex, KEYHANDLER_DIRECTION.RIGHT); - event.stopPropagation(); - } else if (event.key === 'ArrowLeft') { - this.props.context.keyHandler(this.props.index, innerIndex, KEYHANDLER_DIRECTION.LEFT); - event.stopPropagation(); - } else if (event.key === 'Enter' || event.key === ' ') { - event.target.click(); - this.props.enterTriggersArrowDown && - this.props.context.keyHandler(this.props.index, innerIndex, KEYHANDLER_DIRECTION.DOWN); - } - }; - - extendAdditionalChildRef() { - const { additionalChild } = this.props; - - return React.cloneElement(additionalChild as React.ReactElement, { - ref: this.additionalRef - }); - } - - componentRef = (element: HTMLLIElement) => { - (this.ref as React.MutableRefObject).current = element; - const { component } = this.props; - const ref = (component as any).ref; - if (ref) { - if (typeof ref === 'function') { - ref(element); - } else { - (ref as React.MutableRefObject).current = element; - } - } - }; - - render() { - /* eslint-disable @typescript-eslint/no-unused-vars */ - const { - className, - children, - isHovered, - context, - onClick, - component, - role, - isDisabled, - isAriaDisabled, - isPlainText, - index, - href, - tooltip, - tooltipProps, - id, - componentID, - listItemClassName, - additionalChild, - customChild, - enterTriggersArrowDown, - icon, - autoFocus, - styleChildren, - description, - inoperableEvents, - ...additionalProps - } = this.props; - /* eslint-enable @typescript-eslint/no-unused-vars */ - let classes = css(icon && styles.modifiers.icon, isAriaDisabled && styles.modifiers.ariaDisabled, className); - - if (component === 'a') { - additionalProps['aria-disabled'] = isDisabled || isAriaDisabled; - } else if (component === 'button') { - additionalProps['aria-disabled'] = isDisabled || isAriaDisabled; - additionalProps.type = additionalProps.type || 'button'; - } - const renderWithTooltip = (childNode: React.ReactNode) => - tooltip ? ( - - {childNode} - - ) : ( - childNode - ); - - const renderClonedComponent = (element: React.ReactElement) => - React.cloneElement(element, { - ...(styleChildren && { - className: css(element.props.className, classes) - }), - ...(this.props.role !== 'separator' && { ref: this.componentRef }) - }); - - const renderDefaultComponent = (tag: string) => { - const Component = tag as any; - - const componentContent = description ? ( - <> -
    - {icon && {icon}} - {children} -
    -
    {description}
    - - ) : ( - <> - {icon && {icon}} - {children} - - ); - - return ( - - {componentContent} - - ); - }; - - return ( - - {({ onSelect, itemClass, disabledClass, plainTextClass }) => { - if (this.props.role !== 'separator') { - classes = css( - classes, - isDisabled && disabledClass, - isPlainText && plainTextClass, - itemClass, - description && styles.modifiers.description - ); - } - if (customChild) { - return React.cloneElement(customChild as React.ReactElement, { - ref: this.ref, - onKeyDown: this.onKeyDown - }); - } - - return ( -
  • { - if (!isDisabled && !isAriaDisabled) { - onClick(event); - onSelect(event); - } - }} - id={id} - > - {renderWithTooltip( - React.isValidElement(component) - ? renderClonedComponent(component) - : renderDefaultComponent(component as string) - )} - {additionalChild && this.extendAdditionalChildRef()} -
  • - ); - }} - - ); - } -} diff --git a/packages/react-core/src/components/Dropdown/KebabToggle.tsx b/packages/react-core/src/components/Dropdown/KebabToggle.tsx deleted file mode 100644 index 89a6373a9e0..00000000000 --- a/packages/react-core/src/components/Dropdown/KebabToggle.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import { DropdownToggleProps } from './DropdownToggle'; -import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; -import { Toggle } from './Toggle'; - -export interface KebabToggleProps extends DropdownToggleProps { - /** HTML ID of dropdown toggle */ - id?: string; - /** Anything which can be rendered as dropdown toggle */ - children?: React.ReactNode; - /** Classess applied to root element of dropdown toggle */ - className?: string; - /** Flag to indicate if menu is opened */ - isOpen?: boolean; - /** Label Toggle button */ - 'aria-label'?: string; - /** Callback called when toggle is clicked */ - onToggle?: (value: boolean, event: any) => void; - /** Element which wraps toggle */ - parentRef?: any; - /** The menu element */ - getMenuRef?: () => HTMLElement; - /** Forces active state */ - isActive?: boolean; - /** Disables the dropdown toggle */ - isDisabled?: boolean; - /** Display the toggle with no border or background */ - isPlain?: boolean; - /** Type to put on the button */ - type?: 'button' | 'submit' | 'reset'; - /** Allows selecting toggle to select parent */ - bubbleEvent?: boolean; -} - -export const KebabToggle: React.FunctionComponent = ({ - id = '', - // eslint-disable-next-line @typescript-eslint/no-unused-vars - children = null, - className = '', - isOpen = false, - 'aria-label': ariaLabel = 'Actions', - parentRef = null, - getMenuRef = null, - isActive = false, - isPlain = false, - isDisabled = false, - bubbleEvent = false, - onToggle = () => undefined as void, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, // Types of Ref are different for React.FC vs React.Component - ...props -}: KebabToggleProps) => ( - - - -); -KebabToggle.displayName = 'KebabToggle'; diff --git a/packages/react-core/src/components/Dropdown/Toggle.tsx b/packages/react-core/src/components/Dropdown/Toggle.tsx deleted file mode 100644 index a5921d99193..00000000000 --- a/packages/react-core/src/components/Dropdown/Toggle.tsx +++ /dev/null @@ -1,187 +0,0 @@ -import * as React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -import { DropdownContext } from './dropdownConstants'; -import { css } from '@patternfly/react-styles'; -import { KEY_CODES } from '../../helpers/constants'; -import { PickOptional } from '../../helpers/typeUtils'; - -export interface ToggleProps { - /** HTML ID of dropdown toggle */ - id: string; - /** Type to put on the button */ - type?: 'button' | 'submit' | 'reset'; - /** Anything which can be rendered as dropdown toggle */ - children?: React.ReactNode; - /** Classes applied to root element of dropdown toggle */ - className?: string; - /** Flag to indicate if menu is opened */ - isOpen?: boolean; - /** Callback called when toggle is clicked */ - onToggle?: ( - isOpen: boolean, - event: MouseEvent | TouchEvent | KeyboardEvent | React.KeyboardEvent | React.MouseEvent - ) => void; - /** Callback called when the Enter key is pressed */ - onEnter?: () => void; - /** Element which wraps toggle */ - parentRef?: any; - /** The menu element */ - getMenuRef?: () => HTMLElement; - /** Forces active state */ - isActive?: boolean; - /** Disables the dropdown toggle */ - isDisabled?: boolean; - /** Display the toggle with no border or background */ - isPlain?: boolean; - /** Display the toggle in text only mode */ - isText?: boolean; - /** @deprecated Use `toggleVariant` instead. Display the toggle with a primary button style */ - isPrimary?: boolean; - /** Style the toggle as a child of a split button */ - isSplitButton?: boolean; - /** Alternate styles for the dropdown toggle button */ - toggleVariant?: 'primary' | 'secondary' | 'default'; - /** Flag for aria popup */ - 'aria-haspopup'?: boolean | 'listbox' | 'menu' | 'dialog' | 'grid' | 'tree'; - /** Allows selecting toggle to select parent */ - bubbleEvent?: boolean; -} - -const buttonVariantStyles = { - default: '', - primary: styles.modifiers.primary, - secondary: styles.modifiers.secondary -}; - -export class Toggle extends React.Component { - static displayName = 'Toggle'; - private buttonRef = React.createRef(); - - static defaultProps: PickOptional = { - className: '', - isOpen: false, - isActive: false, - isDisabled: false, - isPlain: false, - isText: false, - isPrimary: false, - isSplitButton: false, - onToggle: () => {}, - onEnter: () => {}, - bubbleEvent: false - }; - - componentDidMount = () => { - document.addEventListener('click', this.onDocClick); - document.addEventListener('touchstart', this.onDocClick); - document.addEventListener('keydown', this.onEscPress); - }; - - componentWillUnmount = () => { - document.removeEventListener('click', this.onDocClick); - document.removeEventListener('touchstart', this.onDocClick); - document.removeEventListener('keydown', this.onEscPress); - }; - - onDocClick = (event: MouseEvent | TouchEvent) => { - const { isOpen, parentRef, onToggle, getMenuRef } = this.props; - const menuRef = getMenuRef && getMenuRef(); - const clickedOnToggle = parentRef && parentRef.current && parentRef.current.contains(event.target as Node); - const clickedWithinMenu = menuRef && menuRef.contains && menuRef.contains(event.target as Node); - if (isOpen && !(clickedOnToggle || clickedWithinMenu)) { - onToggle(false, event); - } - }; - - onEscPress = (event: KeyboardEvent) => { - const { parentRef, getMenuRef } = this.props; - const keyCode = event.keyCode || event.which; - const menuRef = getMenuRef && getMenuRef(); - const escFromToggle = parentRef && parentRef.current && parentRef.current.contains(event.target as Node); - const escFromWithinMenu = menuRef && menuRef.contains && menuRef.contains(event.target as Node); - if ( - this.props.isOpen && - (keyCode === KEY_CODES.ESCAPE_KEY || event.key === 'Tab') && - (escFromToggle || escFromWithinMenu) - ) { - this.props.onToggle(false, event); - this.buttonRef.current.focus(); - } - }; - - onKeyDown = (event: React.KeyboardEvent) => { - if (event.key === 'Tab' && !this.props.isOpen) { - return; - } - if ((event.key === 'Tab' || event.key === 'Enter' || event.key === ' ') && this.props.isOpen) { - if (!this.props.bubbleEvent) { - event.stopPropagation(); - } - event.preventDefault(); - - this.props.onToggle(!this.props.isOpen, event); - } else if ((event.key === 'Enter' || event.key === ' ') && !this.props.isOpen) { - if (!this.props.bubbleEvent) { - event.stopPropagation(); - } - event.preventDefault(); - - this.props.onToggle(!this.props.isOpen, event); - this.props.onEnter(); - } - }; - - render() { - const { - className, - children, - isOpen, - isDisabled, - isPlain, - isText, - isPrimary, - isSplitButton, - toggleVariant, - onToggle, - 'aria-haspopup': ariaHasPopup, - /* eslint-disable @typescript-eslint/no-unused-vars */ - isActive, - bubbleEvent, - onEnter, - parentRef, - getMenuRef, - /* eslint-enable @typescript-eslint/no-unused-vars */ - id, - type, - ...props - } = this.props; - return ( - - {({ toggleClass }) => ( - - )} - - ); - } -} diff --git a/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx index 657d7c3e9d5..b8b78399fe5 100644 --- a/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx +++ b/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx @@ -1,245 +1,245 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; -import { Dropdown } from '../Dropdown'; -import { DropdownPosition, DropdownDirection } from '../dropdownConstants'; -import { InternalDropdownItem } from '../InternalDropdownItem'; -import { DropdownSeparator } from '../DropdownSeparator'; -import { DropdownToggle } from '../DropdownToggle'; -import { KebabToggle } from '../KebabToggle'; - -const dropdownItems = [ - Link, - - Action - , - - Disabled Link - , - - Disabled Action - , - , - Separated Link, - - Separated Action - -]; - -describe('dropdown', () => { - test('regular', () => { - const view = mount( - Dropdown
    } /> - ); - expect(view).toMatchSnapshot(); - }); - - test('right aligned', () => { - const view = mount( - Dropdown} - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('alignment breakpoints', () => { - const view = mount( - Dropdown} - isOpen - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('dropup', () => { - const view = mount( - Dropdown} - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('dropup + right aligned', () => { - const view = mount( - Dropdown} - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('expanded', () => { - const view = mount( - Dropdown} - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('primary', () => { - const view = mount( - - Dropdown - - } - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('basic', () => { - const view = mount( - Dropdown}> -
    BASIC
    -
    - ); - expect(view).toMatchSnapshot(); - }); -}); - -describe('KebabToggle', () => { - test('regular', () => { - const view = mount(} />); - expect(view).toMatchSnapshot(); - }); - - test('right aligned', () => { - const view = mount( - } - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('dropup', () => { - const view = mount( - } - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('dropup + right aligned', () => { - const view = mount( - } - /> - ); - expect(view).toMatchSnapshot(); - }); - - test('expanded', () => { - const view = mount(} />); - expect(view).toMatchSnapshot(); - }); - - test('plain', () => { - const view = mount( - } /> - ); - expect(view).toMatchSnapshot(); - }); - - test('basic', () => { - const view = mount( - }> -
    BASIC
    -
    - ); - expect(view).toMatchSnapshot(); - }); -}); - -describe('API', () => { - test('click on item', () => { - const mockToggle = jest.fn(); - const mockSelect = jest.fn(); - const view = mount( - Dropdown} - /> - ); - view - .find('a') - .first() - .simulate('click'); - expect(mockToggle.mock.calls).toHaveLength(0); - expect(mockSelect.mock.calls).toHaveLength(1); - }); - - test('dropdownItems and children console error ', () => { - const myMock = jest.fn(); - global.console = { error: myMock } as any; - mount( - Dropdown} - > -
    Children items
    -
    - ); - expect(myMock).toBeCalledWith( - 'Children and dropdownItems props have been provided. Only the dropdownItems prop items will be rendered' - ); - }); - - test('dropdownItems only, no console error ', () => { - const myMock = jest.fn(); - global.console = { error: myMock } as any; - mount( - Dropdown} - /> - ); - expect(myMock).not.toBeCalled(); - }); - - test('children only, no console ', () => { - const myMock = jest.fn(); - global.console = { error: myMock } as any; - mount( - Dropdown}> -
    Children items
    -
    - ); - expect(myMock).not.toBeCalled(); - }); +import { Dropdown } from '../../Dropdown'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +jest.mock('../../Menu'); + +jest.mock('../../../helpers/Popper/Popper'); + +const toggle = (ref: React.RefObject) => ; + +const dropdownChildren =
    Dropdown children
    ; + +test('renders dropdown', () => { + render( +
    + toggle(toggleRef)}>{dropdownChildren} +
    + ); + + expect(screen.getByTestId('dropdown').children[0]).toBeVisible(); +}); + +test('passes children', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByText('Dropdown children')).toBeVisible(); +}); + +test('renders passed toggle element', () => { + render( toggle(toggleRef)}>{dropdownChildren}); + + expect(screen.getByRole('button', { name: 'Dropdown' })).toBeVisible(); +}); + +test('passes no class name by default', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByTestId('menu-mock')).not.toHaveClass(); +}); + +test('passes custom class name', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByTestId('menu-mock')).toHaveClass('custom-class'); +}); + +test('does not pass isPlain to Menu by default', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByText('isPlain: undefined')).toBeVisible(); +}); + +test('passes isPlain to Menu', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByText('isPlain: true')).toBeVisible(); +}); + +test('does not pass isScrollable to Menu by default', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByText('isScrollable: undefined')).toBeVisible(); +}); + +test('passes isScrollable to Menu', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByText('isScrollable: true')).toBeVisible(); +}); + +test('passes default zIndex to popper', () => { + render( toggle(toggleRef)}>{dropdownChildren}); + + expect(screen.getByText('zIndex: 9999')).toBeVisible(); +}); + +test('passes zIndex to popper', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByText('zIndex: 100')).toBeVisible(); +}); + +test('does not pass isOpen to popper by default', () => { + render( toggle(toggleRef)}>{dropdownChildren}); + + expect(screen.getByText('isVisible: undefined')).toBeVisible(); +}); + +test('passes isOpen to popper', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + expect(screen.getByText('isVisible: true')).toBeVisible(); +}); + +/* no default tests for callback props +since there is no way to test that the +function doesn`t get passed */ + +test('passes onSelect callback', async () => { + const user = userEvent.setup(); + + const onSelect = jest.fn(); + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + const trigger = await screen.findByText('Mock item'); + await user.click(trigger); + + expect(onSelect).toBeCalledTimes(1); +}); + +test('onOpenChange is called when passed and user clicks outside of dropdown', async () => { + const user = userEvent.setup(); + const onOpenChange = jest.fn(); + + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + const dropdown = screen.getByRole('button', { name: 'Dropdown' }); + await user.click(dropdown); + await user.click(document.body); + + expect(onOpenChange).toBeCalledTimes(1); +}); + +test('onOpenChange is called when passed and user presses tab key', async () => { + const user = userEvent.setup(); + const onOpenChange = jest.fn(); + + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + // focus dropdown + const dropdown = screen.getByRole('button', { name: 'Dropdown' }); + await user.click(dropdown); + await user.keyboard('{Tab}'); + + expect(onOpenChange).toBeCalledTimes(1); +}); + +test('onOpenChange is called when passed and user presses esc key', async () => { + const user = userEvent.setup(); + const onOpenChange = jest.fn(); + + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + // focus dropdown + const dropdown = screen.getByRole('button', { name: 'Dropdown' }); + await user.click(dropdown); + await user.keyboard('{Escape}'); + + expect(onOpenChange).toBeCalledTimes(1); +}); + +test('applies containerOuiaId to parent element', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + const dropdownToggle = screen.getByRole('button', { name: 'Dropdown' }); + const dropdownParent = dropdownToggle?.parentNode?.parentNode; + expect(dropdownParent).toHaveAttribute('data-ouia-component-id', 'test-dropdown'); + expect(dropdownParent).toHaveAttribute('data-ouia-component-type', 'PF6/Dropdown container'); + expect(dropdownParent?.tagName).toBe('SPAN'); +}); + +test('Renders with custom container element when containerComponent is passed', () => { + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); + + const dropdownToggle = screen.getByRole('button', { name: 'Dropdown' }); + const dropdownParent = dropdownToggle?.parentNode?.parentNode; + expect(dropdownParent?.tagName).toBe('DIV'); +}); + +test('match snapshot', () => { + const { asFragment } = render( + toggle(toggleRef)} + > + {dropdownChildren} + + ); + + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Dropdown/__tests__/DropdownGroup.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/DropdownGroup.test.tsx index 9d153a7bb3c..789e8a86b6e 100644 --- a/packages/react-core/src/components/Dropdown/__tests__/DropdownGroup.test.tsx +++ b/packages/react-core/src/components/Dropdown/__tests__/DropdownGroup.test.tsx @@ -1,10 +1,67 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownGroup } from '../DropdownGroup'; - -describe('dropdown groups', () => { - test('basic render', () => { - const view = shallow(Something); - expect(view).toMatchSnapshot(); - }); +import { DropdownGroup } from '../../Dropdown'; +import { render, screen } from '@testing-library/react'; +jest.mock('../../Menu'); + +const dropdownGroupChildren =
    Dropdown Group children
    ; + +test('renders dropdown group', () => { + render( +
    + {dropdownGroupChildren} +
    + ); + + expect(screen.getByTestId('dropdown-group').children[0]).toBeVisible(); +}); + +test('passes children', () => { + render({dropdownGroupChildren}); + + expect(screen.getByText('Dropdown Group children')).toBeVisible(); +}); + +test('passes no class name by default', () => { + render({dropdownGroupChildren}); + + expect(screen.getByTestId('menu-group-mock')).not.toHaveClass(); +}); + +test('passes custom class name to MenuGroup', () => { + render({dropdownGroupChildren}); + + expect(screen.getByTestId('menu-group-mock')).toHaveClass('custom-class'); +}); + +test('passes no label by default', () => { + render({dropdownGroupChildren}); + + expect(screen.getByText('label: undefined')).toBeVisible(); +}); + +test('passes custom label to MenuGroup', () => { + render({dropdownGroupChildren}); + + expect(screen.getByText('label: Test label')).toBeVisible(); +}); + +test('passes h1 as labelHeadingLevel to MenuGroup by default', () => { + render({dropdownGroupChildren}); + + expect(screen.getByText('labelHeadingLevel: h1')).toBeVisible(); +}); + +test('passes custom labelHeadingLevel to MenuGroup', () => { + render({dropdownGroupChildren}); + + expect(screen.getByText('labelHeadingLevel: h2')).toBeVisible(); +}); + +test('matches snapshot', () => { + const { asFragment } = render( + + {dropdownGroupChildren} + + ); + + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Dropdown/__tests__/DropdownItem.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/DropdownItem.test.tsx new file mode 100644 index 00000000000..e70b5ca8667 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/__tests__/DropdownItem.test.tsx @@ -0,0 +1,71 @@ +import { DropdownItem } from '../../Dropdown'; +import { render, screen } from '@testing-library/react'; +jest.mock('../../Menu'); + +const dropdownItemChildren =
    Dropdown Item children
    ; + +test('renders dropdown item', () => { + render( +
    + {dropdownItemChildren} +
    + ); + + expect(screen.getByTestId('dropdown-item').children[0]).toBeVisible(); +}); + +test('passes children', () => { + render({dropdownItemChildren}); + + expect(screen.getByText('Dropdown Item children')).toBeVisible(); +}); + +test('passes no class name by default', () => { + render({dropdownItemChildren}); + + expect(screen.getByTestId('menu-item-mock')).not.toHaveClass(); +}); + +test('passes custom class name to MenuItem', () => { + render({dropdownItemChildren}); + + expect(screen.getByTestId('menu-item-mock')).toHaveClass('custom-class'); +}); + +test('passes no description by default', () => { + render({dropdownItemChildren}); + + expect(screen.getByText('description: undefined')).toBeVisible(); +}); + +test('passes custom description to MenuItem', () => { + render({dropdownItemChildren}); + + expect(screen.getByText('description: Test description')).toBeVisible(); +}); + +test('passes no itemId by default', () => { + render({dropdownItemChildren}); + + expect(screen.getByText('itemId: undefined')); +}); + +test('passes itemId to MenuItem', () => { + render( + + {dropdownItemChildren} + + ); + + expect(screen.getByText('itemId: dropdown item')); +}); + +test('matches snapshot', () => { + const { asFragment } = render( + + {dropdownItemChildren} + + ); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/DropdownList.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/DropdownList.test.tsx new file mode 100644 index 00000000000..be2cdf8316a --- /dev/null +++ b/packages/react-core/src/components/Dropdown/__tests__/DropdownList.test.tsx @@ -0,0 +1,39 @@ +import { DropdownList } from '../../Dropdown'; +import { render, screen } from '@testing-library/react'; +jest.mock('../../Menu'); + +const dropdownListChildren =
    Dropdown List children
    ; + +test('renders dropdown list', () => { + render( +
    + {dropdownListChildren} +
    + ); + + expect(screen.getByTestId('dropdown-list').children[0]).toBeVisible(); +}); + +test('passes children', () => { + render({dropdownListChildren}); + + expect(screen.getByText('Dropdown List children')).toBeVisible(); +}); + +test('passes no class name by default', () => { + render({dropdownListChildren}); + + expect(screen.getByTestId('menu-list-mock')).not.toHaveClass(); +}); + +test('passes custom class name to MenuList', () => { + render({dropdownListChildren}); + + expect(screen.getByTestId('menu-list-mock')).toHaveClass('custom-class'); +}); + +test('matches snapshot', () => { + const { asFragment } = render({dropdownListChildren}); + + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/DropdownToggle.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/DropdownToggle.test.tsx deleted file mode 100644 index da3b240eaaf..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/DropdownToggle.test.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; -import { DropdownToggle } from '../DropdownToggle'; -import { DropdownContext } from '../dropdownConstants'; - -describe('API', () => { - test('click on closed', () => { - const mockToggle = jest.fn(); - const view = mount( - - Dropdown - - ); - - view - .find('button') - .first() - .simulate('click'); - expect(mockToggle.mock.calls[0][0]).toBe(true); - }); - - test('click on opened', () => { - const mockToggle = jest.fn(); - const view = mount( - - Dropdown - - ); - - view - .find('button') - .first() - .simulate('click'); - expect(mockToggle.mock.calls[0][0]).toBe(false); - }); - - test('on click outside has been removed', () => { - let mousedown: EventListenerOrEventListenerObject = () => {}; - document.addEventListener = jest.fn((event, cb) => { - mousedown = cb; - }); - document.removeEventListener = jest.fn((event, cb) => { - if (mousedown === cb) { - mousedown = () => {}; - } - }); - const mockToggle = jest.fn(); - const view = mount( - - Dropdown - - ); - view.unmount(); - mousedown({ target: document } as any); - expect(mockToggle.mock.calls).toHaveLength(0); - expect(document.removeEventListener).toHaveBeenCalledWith('click', expect.any(Function)); - }); - - test('on touch outside has been removed', () => { - let touchstart: EventListenerOrEventListenerObject = () => {}; - document.addEventListener = jest.fn((event, cb) => { - touchstart = cb; - }); - document.removeEventListener = jest.fn((event, cb) => { - if (touchstart === cb) { - touchstart = () => {}; - } - }); - const mockToggle = jest.fn(); - const view = mount( - - Dropdown - - ); - view.unmount(); - touchstart({ target: document } as any); - expect(mockToggle.mock.calls).toHaveLength(0); - expect(document.removeEventListener).toHaveBeenCalledWith('touchstart', expect.any(Function)); - }); -}); - -describe('state', () => { - test('hover', () => { - const view = mount( - - Dropdown - - ); - expect(view).toMatchSnapshot(); - }); - - test('active', () => { - const view = mount( - - Dropdown - - ); - expect(view).toMatchSnapshot(); - }); - - test('focus', () => { - const view = mount( - - Dropdown - - ); - expect(view).toMatchSnapshot(); - }); - - test('button variant - primary', () => { - const view = mount( - - Dropdown - - ); - expect(view.find('button').prop('className')).toMatch(/m-primary/); - expect(view).toMatchSnapshot(); - }); - - test('button variant - secondary', () => { - const view = mount( - - Dropdown - - ); - expect(view.find('button').prop('className')).toMatch(/m-secondary/); - expect(view).toMatchSnapshot(); - }); - - test('button variant - secondary', () => { - const view = mount( - - Dropdown - - ); - expect(view.find('button').prop('className')).toMatch(/m-text/); - expect(view.find('button').prop('className')).toMatch(/m-plain/); - expect(view).toMatchSnapshot(); - }); - - test('action split button - renders primary variant', () => { - const view = mount( - test]} - splitButtonVariant="action" - parentRef={document.createElement('div')} - > - Dropdown - - ); - expect(view.find('.pf-c-dropdown__toggle').prop('className')).toMatch(/m-primary/); - expect(view).toMatchSnapshot(); - }); - - test('split button - does not render primary variant', () => { - const view = mount( - test]} - parentRef={document.createElement('div')} - > - Dropdown - - ); - expect(view.find('.pf-c-dropdown__toggle').prop('className')).not.toMatch(/m-primary/); - expect(view).toMatchSnapshot(); - }); - - test('class changes', () => { - const view = mount( - - - Dropdown - - - ); - expect(view).toMatchSnapshot(); - }); - - test('class changes', () => { - const view = mount( - - - Dropdown - - - ); - expect(view).toMatchSnapshot(); - }); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/DropdownToggleAction.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/DropdownToggleAction.test.tsx deleted file mode 100644 index 430bf1eb857..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/DropdownToggleAction.test.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { shallow, mount } from 'enzyme'; -import { DropdownToggleAction } from '../DropdownToggleAction'; - -test('renders with text', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('isDisabled', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('passing class', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('checkbox passes value and event to onClick handler', () => { - const onClickMock = jest.fn(); - const view = mount(); - view.find('button').simulate('click'); - expect(onClickMock).toBeCalled(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/DropdownToggleCheckbox.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/DropdownToggleCheckbox.test.tsx deleted file mode 100644 index c07edcf2838..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/DropdownToggleCheckbox.test.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import * as React from 'react'; -import { shallow, mount } from 'enzyme'; -import { DropdownToggleCheckbox } from '../DropdownToggleCheckbox'; - -const props = { - onChange: jest.fn(), - isChecked: false -}; - -test('controlled', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('uncontrolled', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('with text', () => { - const view = shallow( - - Some text - - ); - expect(view).toMatchSnapshot(); -}); - -test('isDisabled', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('3rd state', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); -}); - -test('passing class', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); - -test('passing HTML attribute', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); -}); - -test('checkbox passes value and event to onChange handler', () => { - const newValue = true; - const event = { - target: { checked: newValue } - }; - const view = mount(); - view.find('input').simulate('change', event); - expect(props.onChange.mock.calls[0][0]).toBe(newValue); - expect(props.onChange.mock.calls[0][1]).toMatchObject(event); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/Dropdown.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/Dropdown.test.tsx deleted file mode 100644 index 25fd29f7d1b..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/Dropdown.test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Dropdown } from '../../Dropdown'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Dropdown should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={'string'} - dropdownItems={[]} - isOpen={true} - isPlain={true} - position={'right'} - direction={'up'} - isGrouped={true} - toggle={

    ReactElement

    } - onSelect={(event?: React.SyntheticEvent) => undefined as void} - autoFocus={true} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownGroup.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownGroup.test.tsx deleted file mode 100644 index fabc6e32049..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownGroup.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownGroup } from '../../DropdownGroup'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DropdownGroup should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} label={''} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownItem.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownItem.test.tsx deleted file mode 100644 index 9849794b2f8..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownItem.test.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownItem } from '../../DropdownItem'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DropdownItem should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - listItemClassName={'string'} - component={'a'} - isDisabled={false} - isPlainText={false} - isHovered={false} - href={'string'} - tooltip={null} - tooltipProps={undefined} - additionalChild={
    ReactNode
    } - customChild={
    ReactNode
    } - icon={null} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownMenu.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownMenu.test.tsx deleted file mode 100644 index 5c4a59d651e..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownMenu.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownMenu } from '../../DropdownMenu'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DropdownMenu should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - isOpen={true} - autoFocus={true} - component={'ul'} - position={'right'} - isGrouped={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownSeparator.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownSeparator.test.tsx deleted file mode 100644 index 32582bc6a3f..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownSeparator.test.tsx +++ /dev/null @@ -1,18 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownSeparator } from '../../DropdownSeparator'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DropdownSeparator should match snapshot (auto-generated)', () => { - const view = shallow( - | React.KeyboardEvent | MouseEvent) => undefined as void} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggle.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggle.test.tsx deleted file mode 100644 index 9872a061d44..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggle.test.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownToggle } from '../../DropdownToggle'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DropdownToggle should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - isOpen={false} - onToggle={(_isOpen: boolean) => undefined as any} - parentRef={null} - isActive={false} - isPlain={false} - isDisabled={false} - isPrimary={false} - icon={null} - toggleIndicator={() =>

    ReactElementType

    } - splitButtonItems={[]} - splitButtonVariant={'checkbox'} - aria-label={'string'} - aria-haspopup={true} - type={'button'} - onEnter={(event?: React.MouseEvent) => undefined as void} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggleAction.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggleAction.test.tsx deleted file mode 100644 index a06e67adfbb..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggleAction.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownToggleAction } from '../../DropdownToggleAction'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DropdownToggleAction should match snapshot (auto-generated)', () => { - const view = shallow( - {}} - children={
    ReactNode
    } - id={'string'} - aria-label={'string'} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggleCheckbox.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggleCheckbox.test.tsx deleted file mode 100644 index d73b8cb05c2..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/DropdownToggleCheckbox.test.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { DropdownToggleCheckbox } from '../../DropdownToggleCheckbox'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('DropdownToggleCheckbox should match snapshot (auto-generated)', () => { - const view = shallow( - undefined as any} - children={
    ReactNode
    } - id={'string'} - aria-label={'string'} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/InternalDropdownItem.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/InternalDropdownItem.test.tsx deleted file mode 100644 index 758adc82387..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/InternalDropdownItem.test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { InternalDropdownItem } from '../../InternalDropdownItem'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('InternalDropdownItem should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - listItemClassName={'string'} - component={'a'} - role={"'none'"} - isDisabled={false} - isPlainText={false} - isHovered={false} - href={'string'} - tooltip={
    ReactNode
    } - tooltipProps={undefined} - index={-1} - context={{ - keyHandler: () => {}, - sendRef: () => {} - }} - onClick={(event: React.MouseEvent | React.KeyboardEvent | MouseEvent) => undefined as any} - id={'string'} - componentID={'string'} - additionalChild={
    ReactNode
    } - customChild={
    ReactNode
    } - enterTriggersArrowDown={false} - icon={
    ReactNode
    } - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/KebabToggle.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/KebabToggle.test.tsx deleted file mode 100644 index 083e874399c..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/KebabToggle.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { KebabToggle } from '../../KebabToggle'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('KebabToggle should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - isOpen={false} - aria-label={"'Actions'"} - onToggle={() => undefined as void} - parentRef={null} - isActive={false} - isDisabled={false} - isPlain={false} - type={'button'} - bubbleEvent={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/Toggle.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Generated/Toggle.test.tsx deleted file mode 100644 index 50be9bcbac3..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/Toggle.test.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { Toggle } from '../../Toggle'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('Toggle should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - isOpen={false} - onToggle={() => {}} - onEnter={() => {}} - parentRef={'any'} - isActive={false} - isDisabled={false} - isPlain={false} - isPrimary={false} - isSplitButton={false} - aria-haspopup={true} - bubbleEvent={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/Dropdown.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/Dropdown.test.tsx.snap deleted file mode 100644 index 9e4a3f6c7de..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/Dropdown.test.tsx.snap +++ /dev/null @@ -1,51 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Dropdown should match snapshot (auto-generated) 1`] = ` - - - ReactElement -

    - } - > -
    - ReactNode -
    -
    -
    -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownGroup.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownGroup.test.tsx.snap deleted file mode 100644 index 01c90d71ed1..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownGroup.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DropdownGroup should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownItem.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownItem.test.tsx.snap deleted file mode 100644 index eab0f6f5d3d..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownItem.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DropdownItem should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownMenu.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownMenu.test.tsx.snap deleted file mode 100644 index c5e2f116485..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownMenu.test.tsx.snap +++ /dev/null @@ -1,16 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DropdownMenu should match snapshot (auto-generated) 1`] = ` - - - - - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownSeparator.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownSeparator.test.tsx.snap deleted file mode 100644 index fdacd87ad7c..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownSeparator.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DropdownSeparator should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggle.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggle.test.tsx.snap deleted file mode 100644 index 547e9388c24..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggle.test.tsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DropdownToggle should match snapshot (auto-generated) 1`] = ` -
    - - - -
    -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggleAction.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggleAction.test.tsx.snap deleted file mode 100644 index be5eaa8a9e1..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggleAction.test.tsx.snap +++ /dev/null @@ -1,14 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DropdownToggleAction should match snapshot (auto-generated) 1`] = ` - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggleCheckbox.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggleCheckbox.test.tsx.snap deleted file mode 100644 index e8499dc4639..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/DropdownToggleCheckbox.test.tsx.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DropdownToggleCheckbox should match snapshot (auto-generated) 1`] = ` - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/InternalDropdownItem.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/InternalDropdownItem.test.tsx.snap deleted file mode 100644 index e48e5a613cc..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/InternalDropdownItem.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`InternalDropdownItem should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/KebabToggle.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/KebabToggle.test.tsx.snap deleted file mode 100644 index bd632d5ff90..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/KebabToggle.test.tsx.snap +++ /dev/null @@ -1,28 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`KebabToggle should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/Toggle.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/Toggle.test.tsx.snap deleted file mode 100644 index 53ff23b6334..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Generated/__snapshots__/Toggle.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Toggle should match snapshot (auto-generated) 1`] = ` - - - -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/InternalDropdownItem.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/InternalDropdownItem.test.tsx deleted file mode 100644 index c57da977b8e..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/InternalDropdownItem.test.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { InternalDropdownItem } from '../InternalDropdownItem'; -import { DropdownSeparator } from '../DropdownSeparator'; - -describe('dropdown items', () => { - test('a', () => { - const view = shallow(Something); - expect(view).toMatchSnapshot(); - }); - - test('button', () => { - const view = shallow(Something); - expect(view).toMatchSnapshot(); - }); - - test('separator', () => { - const view = shallow(); - expect(view).toMatchSnapshot(); - }); - - describe('hover', () => { - test('a', () => { - const view = shallow(Something); - expect(view).toMatchSnapshot(); - }); - test('button', () => { - const view = shallow( - - Something - - ); - expect(view).toMatchSnapshot(); - }); - }); - - describe('disabled', () => { - test('a', () => { - const view = shallow(Something); - expect(view).toMatchSnapshot(); - }); - test('button', () => { - const view = shallow( - - Something - - ); - expect(view).toMatchSnapshot(); - }); - }); - - describe('aria-disabled', () => { - test('a', () => { - const view = shallow(Something); - expect(view).toMatchSnapshot(); - }); - test('button', () => { - const view = shallow( - - Something - - ); - expect(view).toMatchSnapshot(); - }); - }); - - describe('description', () => { - test('a', () => { - const view = shallow( - - Something - - ); - expect(view).toMatchSnapshot(); - }); - test('button', () => { - const view = shallow( - - Something - - ); - expect(view).toMatchSnapshot(); - }); - }) -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Toggle.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Toggle.test.tsx deleted file mode 100644 index 2904b8702a9..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/Toggle.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import { mount } from 'enzyme'; -import { DropdownToggle } from '../DropdownToggle'; -import { KebabToggle } from '../KebabToggle'; - -test('Dropdown toggle', () => { - const view = mount(Dropdown); - expect(view).toMatchSnapshot(); -}); -test('Kebab toggle', () => { - const view = mount(); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap index 6a0e99b3e53..2f34150f2e9 100644 --- a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap +++ b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap @@ -1,9022 +1,66 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`KebabToggle basic 1`] = ` - - } -> - - } +exports[`match snapshot 1`] = ` + +
    - - -
    -
    - BASIC -
    -
    -
    , - } - } - > - - -
    -
    - BASIC -
    -
    -
    , - } - } - > - -
    -
    - - - - - -
    -`; - -exports[`KebabToggle dropup + right aligned 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - position="right" - toggle={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="right" - toggle={ - - } - > -
    - - -
    , - } - } - > - - - , - } - } - > - - -
    - -
    -
    -`; - -exports[`KebabToggle dropup 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - toggle={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - } - > -
    - - -
    , - } - } - > - - - , - } - } - > - - -
    - -
    -
    -`; - -exports[`KebabToggle expanded 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isOpen={true} - toggle={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={true} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - } - > -
    - - - -
    , - } - } - > - - - - , - } - } - > - - -
    - - - - -
    -
    -`; - -exports[`KebabToggle plain 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isPlain={true} - toggle={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={true} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - } - > -
    - - -
    , - } - } - > - - - , - } - } - > - - -
    - -
    -
    -`; - -exports[`KebabToggle regular 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - toggle={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - } - > -
    - - -
    , - } - } - > - - - , - } - } - > - - -
    - -
    -
    -`; - -exports[`KebabToggle right aligned 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - position="right" - toggle={ - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="right" - toggle={ - - } - > -
    - - -
    , - } - } - > - - - , - } - } - > - - -
    - -
    -
    -`; - -exports[`dropdown alignment breakpoints 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isOpen={true} - toggle={ - - Dropdown - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={true} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - Dropdown - - } - > -
    - - - -
    , - } - } - > - - - - , - } - } - toggleVariant="default" - > - - - - - - - -
    -
    -`; - -exports[`dropdown basic 1`] = ` - - Dropdown - - } -> - - Dropdown - - } - > -
    - - -
    -
    - BASIC -
    -
    -
    , - } - } - > - - -
    -
    - BASIC -
    -
    - , - } - } - toggleVariant="default" - > - -
    - - - -
    -
    -`; - -exports[`dropdown dropup 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - toggle={ - - Dropdown - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - Dropdown - - } - > -
    - - -
    , - } - } - > - - - , - } - } - toggleVariant="default" - > - - - - -
    -
    -`; - -exports[`dropdown expanded 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isOpen={true} - toggle={ - - Dropdown - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={true} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - Dropdown - - } - > -
    - - - -
    , - } - } - > - - - - , - } - } - toggleVariant="default" - > - - - - - - - -
    -
    -`; - -exports[`dropdown primary 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - toggle={ - - Dropdown - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - Dropdown - - } - > -
    - - -
    , - } - } - > - - - , - } - } - toggleVariant="default" - > - - - - -
    -
    -`; - -exports[`dropdown regular 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - toggle={ - - Dropdown - - } -> - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - isGrouped={false} - isOpen={false} - isPlain={false} - isText={false} - menuAppendTo="inline" - onSelect={[Function]} - position="left" - toggle={ - - Dropdown - - } - > -
    - - -
    , - } - } - > - - - , - } - } - toggleVariant="default" - > - - - + +
    + Mock item +
    +

    + isPlain: true +

    +

    + isScrollable: true +

    +

    + minWidth: undefined +

    -
    -
    -`; - -exports[`dropdown right aligned 1`] = ` - - Link - , - - Action - , - - Disabled Link - , - - Disabled Action - , - , - - Separated Link - , - - Separated Action - , - ] - } - position="right" - toggle={ - +

    + zIndex: 9999 +

    +

    + isVisible: true +

    +

    + enableFlip: undefined +

    +

    + placement: undefined +

    +

    + appendTo: undefined +

    +

    + distance: undefined +

    +

    + flipBehavior: undefined +

    +

    + minWidth: undefined +

    + - , - } - } - > - - - , - } - } - toggleVariant="default" - > - - -
    - - -
    + + +
    `; diff --git a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownGroup.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownGroup.test.tsx.snap index 57420c4f469..12277b3b888 100644 --- a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownGroup.test.tsx.snap +++ b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownGroup.test.tsx.snap @@ -1,7 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`dropdown groups basic render 1`] = ` - - - +exports[`matches snapshot 1`] = ` + +
    +
    + Dropdown Group children +
    +
    +

    + label: Test label +

    +

    + labelHeadingLevel: h2 +

    +
    `; diff --git a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownItem.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownItem.test.tsx.snap new file mode 100644 index 00000000000..b814290d162 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownItem.test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`matches snapshot 1`] = ` + +
    +
    + Dropdown Item children +
    +
    +

    + description: Test description +

    +

    + itemId: undefined +

    +
    +`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownList.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownList.test.tsx.snap new file mode 100644 index 00000000000..1e25ffb9bf4 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownList.test.tsx.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`matches snapshot 1`] = ` + +
    +
    + Dropdown List children +
    +
    +
    +`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownToggle.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownToggle.test.tsx.snap deleted file mode 100644 index 40e16c120d1..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownToggle.test.tsx.snap +++ /dev/null @@ -1,795 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`state action split button - renders primary variant 1`] = ` -} - splitButtonItems={ - Array [ -
    - test -
    , - ] - } - splitButtonVariant="action" - toggleVariant="primary" -> -
    -
    - test -
    - } - toggleVariant="primary" - > - - -
    -
    -`; - -exports[`state active 1`] = ` -} -> - } - toggleVariant="default" - > - - - -`; - -exports[`state button variant - primary 1`] = ` -} - toggleVariant="primary" -> - } - toggleVariant="primary" - > - - - -`; - -exports[`state button variant - secondary 1`] = ` -} - toggleVariant="secondary" -> - } - toggleVariant="secondary" - > - - - -`; - -exports[`state button variant - secondary 2`] = ` -} -> - } - toggleVariant="default" - > - - - -`; - -exports[`state class changes 1`] = ` -} -> - } - toggleVariant="default" - > - - - -`; - -exports[`state class changes 2`] = ` -} -> - } - toggleVariant="default" - > - - - -`; - -exports[`state focus 1`] = ` -} -> - } - toggleVariant="default" - > - - - -`; - -exports[`state hover 1`] = ` -} -> - } - toggleVariant="default" - > - - - -`; - -exports[`state split button - does not render primary variant 1`] = ` -} - splitButtonItems={ - Array [ -
    - test -
    , - ] - } - toggleVariant="primary" -> -
    -
    - test -
    - } - toggleVariant="primary" - > - - -
    -
    -`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownToggleAction.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownToggleAction.test.tsx.snap deleted file mode 100644 index 3ea11b5b6ec..00000000000 --- a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/DropdownToggleAction.test.tsx.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`isDisabled 1`] = ` - - - -`; - -exports[`Kebab toggle 1`] = ` - - - - - -`; diff --git a/packages/react-core/src/components/Dropdown/dropdownConstants.tsx b/packages/react-core/src/components/Dropdown/dropdownConstants.tsx deleted file mode 100644 index 7fef954b781..00000000000 --- a/packages/react-core/src/components/Dropdown/dropdownConstants.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import * as React from 'react'; -import { OUIAProps } from '../../helpers'; - -export enum DropdownPosition { - right = 'right', - left = 'left' -} - -export enum DropdownDirection { - up = 'up', - down = 'down' -} - -export const DropdownContext = React.createContext< - { - onSelect?: (event?: any) => void; - id?: string; - toggleIndicatorClass?: string; - toggleIconClass?: string; - toggleTextClass?: string; - menuClass?: string; - itemClass?: string; - toggleClass?: string; - baseClass?: string; - baseComponent?: string; - sectionClass?: string; - sectionTitleClass?: string; - sectionComponent?: string; - disabledClass?: string; - plainTextClass?: string; - menuComponent?: string; - ouiaComponentType?: string; - alignments?: { - sm?: 'right' | 'left'; - md?: 'right' | 'left'; - lg?: 'right' | 'left'; - xl?: 'right' | 'left'; - '2xl'?: 'right' | 'left'; - }; - } & OUIAProps ->({ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onSelect: (event?: any) => undefined as any, - id: '', - toggleIndicatorClass: '', - toggleIconClass: '', - toggleTextClass: '', - menuClass: '', - itemClass: '', - toggleClass: '', - baseClass: '', - baseComponent: 'div', - sectionClass: '', - sectionTitleClass: '', - sectionComponent: 'section', - disabledClass: '', - plainTextClass: '', - menuComponent: 'ul' -}); - -export const DropdownArrowContext = React.createContext({ - keyHandler: null, - sendRef: null -}); diff --git a/packages/react-core/src/components/Dropdown/examples/Dropdown.md b/packages/react-core/src/components/Dropdown/examples/Dropdown.md index 43383bf8ba9..4e0cf97fe46 100644 --- a/packages/react-core/src/components/Dropdown/examples/Dropdown.md +++ b/packages/react-core/src/components/Dropdown/examples/Dropdown.md @@ -1,1612 +1,77 @@ --- id: Dropdown section: components -cssPrefix: pf-c-dropdown +subsection: menus +cssPrefix: pf-v6-c-menu propComponents: - ['Dropdown', 'DropdownGroup', 'DropdownItem', 'DropdownToggle', 'DropdownToggleCheckbox', 'DropdownToggleAction'] -ouia: true + [ + 'Dropdown', + 'DropdownGroup', + 'DropdownItem', + 'DropdownList', + 'MenuToggle', + 'DropdownToggleProps', + 'TooltipProps', + 'PopperOptions' + ] --- -import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; -import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; -import { Link } from '@reach/router'; -import avatarImg from '../../Avatar/examples/avatarImg.svg'; +import { useState, useRef } from 'react'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; ## Examples -### Basic +`Dropdown` builds off of the Menu component suite to wrap commonly used properties and functions for a dropdown menu. See the [Menu documentation](/components/menus/menu) for a full list of properties that may be passed through `Dropdown` to further customize the dropdown menu, or the [custom menu examples](/components/menus/custom-menus) for additional examples of fully functional menus. -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; +### Basic dropdowns -class SimpleDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id'); - element.focus(); - }; - } +Basic dropdowns present users with a menu of items upon clicking a dropdown toggle. - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### With initial selection - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; - -class IntialSelectionDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-2'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - autoFocus={false} - /> - ); - } -} -``` - -### With groups - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownGroup, DropdownItem } from '@patternfly/react-core'; - -class GroupedDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-3'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - - Link - - Action - - , - - Group 2 link - - Group 2 action - - , - - Group 3 link - - Group 3 action - - - ]; - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - isGrouped - /> - ); - } -} -``` - -### Disabled - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; - -class DisabledDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Primary toggle - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; - -class PrimaryDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-4'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Secondary toggle - -```ts -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; - -const SecondaryDropdown = () => { - const [isOpen, setIsOpen] = React.useState(false); - - const onFocus = () => { - const element = document.getElementById('toggle-id-secondary'); - element.focus(); - }; - - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - - return ( - { - setIsOpen(!isOpen); - onFocus(); - }} - toggle={ - setIsOpen(next)} - toggleIndicator={CaretDownIcon} - toggleVariant="secondary" - id="toggle-id-secondary" - > - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); -}; -``` - -### Plain with text toggle - -```ts -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; - -const SecondaryDropdown = () => { - const [isOpen, setIsOpen] = React.useState(false); - - const onFocus = () => { - const element = document.getElementById('toggle-id-plain-text'); - element.focus(); - }; - - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - - return ( - { - setIsOpen(!isOpen); - onFocus(); - }} - toggle={ - setIsOpen(next)} - toggleIndicator={CaretDownIcon} - id="toggle-id-plain-text" - > - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); -}; -``` - -### Position right - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator, DropdownPosition } from '@patternfly/react-core'; - -class PositionRightDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-5'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - Dropdown} - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Alignments on different breakpoints - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; - -class AlignmentsDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-5'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - Dropdown} - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Direction up - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator, DropdownDirection } from '@patternfly/react-core'; +A `` uses a [menu toggle](/components/menus/menu-toggle), which is passed to the `toggle` property, as well as a `` with multiple `` components. To allow a dropdown to change the open state of the menu, pass the `isOpen` property into the `onOpenChange` callback. -class DirectionUpDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } +The following example shows a few different states of dropdown items. As shown in this example, dropdown items may: - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### With kebab - -```js -import React from 'react'; -import { Dropdown, DropdownItem, DropdownSeparator, KebabToggle } from '@patternfly/react-core'; - -class KebabDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-6'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - } - isOpen={isOpen} - isPlain - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### With badge - -```js -import React from 'react'; -import { Dropdown, DropdownItem, BadgeToggle } from '@patternfly/react-core'; -import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; - -class BadgeDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - }> - Edit - , - }> - Deployment - , - }> - Applications - - ]; - return ( - - {dropdownItems.length} - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Icon only +- Use the `isDisabled` property to disable an item. +- Use the `onClick` property to trigger a callback for an action. -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem, DropdownSeparator } from '@patternfly/react-core'; -import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon'; +This example also uses a `` which passes in `key=”separator”` to split the menu into 2 sections with a horizontal line. -class IconDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-7'); - element.focus(); - }; - } +```ts file="./DropdownBasic.tsx" - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - - - } - isOpen={isOpen} - isPlain - dropdownItems={dropdownItems} - /> - ); - } -} ``` -### Split button +### With kebab toggle -```js -import React from 'react'; -import { - Dropdown, - DropdownToggle, - DropdownToggleCheckbox, - DropdownItem, - DropdownSeparator -} from '@patternfly/react-core'; +To style a dropdown menu's toggle with a kebab icon, pass a "plain" `` to the `toggle` property. When there isn't enough space for a labeled button, a kebab icon can be used to toggle the dropdown menu open or closed. -class SplitButtonDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-8'); - element.focus(); - }; - } +```ts file="./DropdownWithKebabToggle.tsx" - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - ]} - onToggle={this.onToggle} - id="toggle-id-8" - /> - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} ``` -### Split button (with text) +### With groups of items -```js -import React from 'react'; -import { - Dropdown, - DropdownToggle, - DropdownToggleCheckbox, - DropdownItem, - DropdownSeparator -} from '@patternfly/react-core'; +To group sets of related dropdown items together, use a ``. When more than 1 `` is created in a menu, use the `label` and `labelHeadingLevel` properties to assign a name and heading level to each group. -class SplitButtonDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } +```ts file="./DropdownWithGroups.tsx" - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - 10 selected - - ]} - onToggle={this.onToggle} - /> - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} ``` -### Split button (3rd state) +### With item descriptions -```js -import React from 'react'; -import { - Dropdown, - DropdownToggle, - DropdownToggleCheckbox, - DropdownItem, - DropdownSeparator -} from '@patternfly/react-core'; -class SplitButtonDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false, - isChecked: null - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - this.onChange = isChecked => { - this.setState({ - isChecked - }); - }; - } - render() { - const { isOpen, isChecked } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - this.onChange(checked)} - isChecked={isChecked} - /> - ]} - onToggle={this.onToggle} - /> - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Split button (disabled) - -```js -import React from 'react'; -import { - Dropdown, - DropdownToggle, - DropdownToggleCheckbox, - DropdownItem, - DropdownSeparator -} from '@patternfly/react-core'; - -class SplitButtonDisabledDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - Link, - - Action - , - - Disabled link - , - - Disabled action - , - , - Separated link, - - Separated action - - ]; - return ( - - ]} - isDisabled - onToggle={this.onToggle} - /> - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` +To provide users with more context about a ``, pass a short message to `description` property. As shown in the example below, an item's description will appear below its label. -### Split button action +```ts file="./DropdownWithDescriptions.tsx" -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownToggleAction, DropdownItem } from '@patternfly/react-core'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; - -class SplitButtonActionDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isActionOpen: false, - isCogOpen: false - }; - this.onActionToggle = isActionOpen => { - this.setState({ - isActionOpen - }); - }; - this.onCogToggle = isCogOpen => { - this.setState({ - isCogOpen - }); - }; - this.onActionClick = event => { - window.alert('You selected an action button!'); - }; - this.onCogClick = event => { - window.alert('You selected the Cog!'); - }; - this.onActionSelect = event => { - this.setState({ - isActionOpen: !this.state.isActionOpen - }); - }; - this.onCogSelect = event => { - this.setState({ - isCogOpen: !this.state.isCogOpen - }); - }; - } - - render() { - const { isActionOpen, isCogOpen } = this.state; - const dropdownItems = [ - - Action - , - - Disabled action - , - - Other action - - ]; - const dropdownIconItems = [ - } onClick={this.onActionClick}> - Action - , - } isDisabled onClick={this.onActionClick}> - Disabled action - , - } onClick={this.onActionClick}> - Other action - - ]; - return ( - - - Action - - ]} - splitButtonVariant="action" - onToggle={this.onActionToggle} - /> - } - isOpen={isActionOpen} - dropdownItems={dropdownItems} - />{' '} - - - - ]} - splitButtonVariant="action" - onToggle={this.onCogToggle} - /> - } - isOpen={isCogOpen} - dropdownItems={dropdownIconItems} - /> - - ); - } -} ``` -### Split button primary action - -```ts -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownToggleAction, DropdownItem } from '@patternfly/react-core'; -import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; -import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; - -const PrimarySplitActionDropdown = () => { - const [isActionOpen, setIsActionOpen] = React.useState(false); - const [isCogOpen, setIsCogOpen] = React.useState(false); - - const onActionClick = () => { - window.alert('You selected an action button!'); - }; - const onCogClick = () => { - window.alert('You selected the Cog!'); - }; - - const dropdownItems = [ - - Action - , - - Disabled action - , - - Other action - - ]; - const dropdownIconItems = [ - } onClick={onActionClick}> - Action - , - } isDisabled onClick={onActionClick}> - Disabled action - , - } onClick={onActionClick}> - Other action - - ]; - - return ( - - setIsActionOpen(!isActionOpen)} - toggle={ - - Action - - ]} - toggleVariant="primary" - splitButtonVariant="action" - onToggle={next => setIsActionOpen(next)} - /> - } - isOpen={isActionOpen} - dropdownItems={dropdownItems} - />{' '} - setIsCogOpen(!isCogOpen)} - toggle={ - - - - ]} - toggleVariant="primary" - splitButtonVariant="action" - onToggle={next => setIsCogOpen(next)} - /> - } - isOpen={isCogOpen} - dropdownItems={dropdownIconItems} - /> - - ); -}; -``` - -### Basic panel - -```js -import React from 'react'; -import { Dropdown, DropdownToggle } from '@patternfly/react-core'; - -class DropdownPanel extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - }; - } - - render() { - const { isOpen } = this.state; - return ( - Expanded dropdown} - isOpen={isOpen} - > - [Panel contents here] - - ); - } -} -``` - -### Router link - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem } from '@patternfly/react-core'; -import { Link } from '@reach/router'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; - -class RouterDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-8'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [@reach/router Link} />]; - - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Dropdown with image and text - -```js -import React from 'react'; -import { - Avatar, - Dropdown, - DropdownGroup, - DropdownToggle, - DropdownItem, - DropdownSeparator -} from '@patternfly/react-core'; -import avatarImg from '../../Avatar/examples/avatarImg.svg'; - -class ImageTextDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-9'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [ - - - Text - - - More text - - , - , - - My profile - - User management - - Logout - - ]; - return ( -
    } - > - Ned Username - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} -``` - -### Append menu document body - -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem } from '@patternfly/react-core'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; - -class MenuOnDocumentBodyDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id-menu-document-body'); - element.focus(); - }; - } - - render() { - const { isOpen } = this.state; - const dropdownItems = [1]; - return ( -
    - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - menuAppendTo={() => document.body} - /> -
    - ); - } -} -``` +### Split toggle with checkbox -### Dropdown with descriptions +To combine a checkbox or other control with a dropdown menu, use a split button. -```js -import React from 'react'; -import { Dropdown, DropdownToggle, DropdownItem } from '@patternfly/react-core'; -import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; -import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; +A `` can be rendered as a split button via `splitButtonItems`. Elements to be displayed before the dropdown toggle button (like the ``) must be included in the `splitButtonItems`. -class SimpleDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.onToggle = isOpen => { - this.setState({ - isOpen - }); - }; - this.onSelect = event => { - this.setState({ - isOpen: !this.state.isOpen - }); - this.onFocus(); - }; - this.onFocus = () => { - const element = document.getElementById('toggle-id'); - element.focus(); - }; - } +If the dropdown menu closes upon selection, you will need to manually shift focus back to the toggle element after a user selects an item from the menu. - render() { - const { isOpen } = this.state; +```ts file="./DropdownWithSplit.tsx" - const dropdownItems = [ - }> - Link - , - } - description="This is a very long description that describes the menu item" - > - Action - , - - Disabled link - , - - Disabled action - - ]; - return ( - - Dropdown - - } - isOpen={isOpen} - dropdownItems={dropdownItems} - /> - ); - } -} ``` diff --git a/packages/react-core/src/components/Dropdown/examples/DropdownBasic.tsx b/packages/react-core/src/components/Dropdown/examples/DropdownBasic.tsx new file mode 100644 index 00000000000..846a846a0b4 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/examples/DropdownBasic.tsx @@ -0,0 +1,68 @@ +import { useState } from 'react'; +import { Dropdown, DropdownItem, DropdownList, Divider, MenuToggle, MenuToggleElement } from '@patternfly/react-core'; + +export const DropdownBasic: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = useState(false); + + const onToggleClick = () => { + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, value: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', value); + setIsOpen(false); + }; + + return ( + setIsOpen(isOpen)} + toggle={(toggleRef: React.Ref) => ( + + Dropdown + + )} + ouiaId="BasicDropdown" + shouldFocusToggleOnSelect + > + + + Action + + ev.preventDefault()} + > + Link + + + Disabled Action + + + Disabled Link + + + Aria-disabled Link + + + + Separated Action + + ev.preventDefault()}> + Separated Link + + + + ); +}; diff --git a/packages/react-core/src/components/Dropdown/examples/DropdownWithDescriptions.tsx b/packages/react-core/src/components/Dropdown/examples/DropdownWithDescriptions.tsx new file mode 100644 index 00000000000..2cd8eb484a0 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/examples/DropdownWithDescriptions.tsx @@ -0,0 +1,52 @@ +import { useState } from 'react'; +import { Dropdown, DropdownItem, DropdownList, MenuToggle, MenuToggleElement } from '@patternfly/react-core'; + +export const DropdownWithDescriptions: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = useState(false); + + const onToggleClick = () => { + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, value: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', value); + setIsOpen(false); + }; + + return ( + setIsOpen(isOpen)} + toggle={(toggleRef: React.Ref) => ( + + Dropdown + + )} + shouldFocusToggleOnSelect + > + + + Action + + ev.preventDefault()} + > + Link + + + Disabled action + + + Disabled link + + + + ); +}; diff --git a/packages/react-core/src/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/components/Dropdown/examples/DropdownWithGroups.tsx new file mode 100644 index 00000000000..7a68605eda1 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/examples/DropdownWithGroups.tsx @@ -0,0 +1,77 @@ +import { useState } from 'react'; +import { + Dropdown, + DropdownGroup, + DropdownItem, + DropdownList, + MenuToggle, + MenuToggleElement, + Divider +} from '@patternfly/react-core'; + +export const DropdownWithGroups: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = useState(false); + + const onToggleClick = () => { + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, value: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', value); + setIsOpen(false); + }; + + return ( + setIsOpen(isOpen)} + toggle={(toggleRef: React.Ref) => ( + + Dropdown + + )} + shouldFocusToggleOnSelect + > + + + + Action + + ev.preventDefault()} + > + Link + + + + + + + + Group 2 action + + ev.preventDefault()}> + Group 2 link + + + + + + + + Group 3 action + + ev.preventDefault()}> + Group 3 link + + + + + ); +}; diff --git a/packages/react-core/src/components/Dropdown/examples/DropdownWithKebabToggle.tsx b/packages/react-core/src/components/Dropdown/examples/DropdownWithKebabToggle.tsx new file mode 100644 index 00000000000..6dc43da0604 --- /dev/null +++ b/packages/react-core/src/components/Dropdown/examples/DropdownWithKebabToggle.tsx @@ -0,0 +1,64 @@ +import { useState } from 'react'; +import { Dropdown, DropdownItem, DropdownList, Divider, MenuToggle, MenuToggleElement } from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +export const DropdownWithKebab: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = useState(false); + + const onToggleClick = () => { + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, value: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', value); + setIsOpen(false); + }; + + return ( + setIsOpen(isOpen)} + toggle={(toggleRef: React.Ref) => ( + } + /> + )} + shouldFocusToggleOnSelect + > + + + Action + + ev.preventDefault()} + > + Link + + + Disabled Action + + + Disabled Link + + + + Separated Action + + ev.preventDefault()}> + Separated Link + + + + ); +}; diff --git a/packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx b/packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx new file mode 100644 index 00000000000..140a99510cd --- /dev/null +++ b/packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx @@ -0,0 +1,97 @@ +import { + Dropdown, + MenuToggle, + MenuToggleCheckbox, + DropdownItem, + DropdownList, + Divider, + MenuToggleElement +} from '@patternfly/react-core'; +import { useRef, useState } from 'react'; + +export const DropdownSplitButtonText: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = useState(false); + const toggleRef = useRef(null); + + const onFocus = () => { + if (!toggleRef.current) { + return; + } + + const toggleButton = toggleRef.current.querySelector('button[aria-expanded]'); + toggleButton?.focus(); + }; + + const onSelect = () => { + setIsOpen(false); + onFocus(); + }; + + const onToggleClick = () => { + setIsOpen(!isOpen); + }; + + return ( + setIsOpen(isOpen)} + toggle={(toggleRefCallback: React.Ref) => ( + { + // Handle both callback ref and useRef + if (typeof toggleRefCallback === 'function') { + toggleRefCallback(node); + } else if (toggleRefCallback) { + (toggleRefCallback as React.MutableRefObject).current = node; + } + (toggleRef as React.MutableRefObject).current = node; + }} + splitButtonItems={[ + + ]} + aria-label="Dropdown with checkbox split button" + onClick={onToggleClick} + isExpanded={isOpen} + /> + )} + isOpen={isOpen} + > + + + Action + + ev.preventDefault()} + > + Link + + + Disabled Action + + + Disabled Link + + + Aria-disabled Link + + + + Separated Action + + ev.preventDefault()}> + Separated Link + + + + ); +}; diff --git a/packages/react-core/src/components/Dropdown/index.ts b/packages/react-core/src/components/Dropdown/index.ts index b7ec6230d01..0edc20d91ad 100644 --- a/packages/react-core/src/components/Dropdown/index.ts +++ b/packages/react-core/src/components/Dropdown/index.ts @@ -1,12 +1,4 @@ export * from './Dropdown'; -export * from './DropdownMenu'; -export * from './DropdownWithContext'; -export * from './dropdownConstants'; export * from './DropdownGroup'; export * from './DropdownItem'; -export * from './DropdownSeparator'; -export * from './BadgeToggle'; -export * from './KebabToggle'; -export * from './DropdownToggle'; -export * from './DropdownToggleCheckbox'; -export * from './DropdownToggleAction'; +export * from './DropdownList'; diff --git a/packages/react-core/src/components/DualListSelector/DualListSelector.tsx b/packages/react-core/src/components/DualListSelector/DualListSelector.tsx index 5c7070913f6..1c21c05f3f4 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelector.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelector.tsx @@ -1,737 +1,50 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; import { css } from '@patternfly/react-styles'; -import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; -import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; -import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; -import { DualListSelectorPane } from './DualListSelectorPane'; -import { getUniqueId, PickOptional } from '../../helpers'; -import { DualListSelectorTreeItemData } from './DualListSelectorTree'; -import { - flattenTree, - flattenTreeWithFolders, - filterFolders, - filterTreeItems, - filterTreeItemsWithoutFolders, - filterRestTreeItems -} from './treeUtils'; -import { DualListSelectorControlsWrapper } from './DualListSelectorControlsWrapper'; -import { DualListSelectorControl } from './DualListSelectorControl'; +import { useSSRSafeId } from '../../helpers'; import { DualListSelectorContext } from './DualListSelectorContext'; +import { useHasAnimations } from '../../helpers'; + +/** Acts as a container for all other DualListSelector sub-components when using a + * composable dual list selector. + */ export interface DualListSelectorProps { /** Additional classes applied to the dual list selector. */ className?: string; - /** Id of the dual list selector. */ + /** ID of the dual list selector. */ id?: string; - /** Flag indicating if the dual list selector uses trees instead of simple lists */ + /** Flag indicating if the dual list selector uses trees instead of simple lists. */ isTree?: boolean; - /** Flag indicating if the dual list selector is in a disabled state */ - isDisabled?: boolean; - /** Content to be rendered in the dual list selector. Panes & controls will not be built dynamically when children are provided. */ + /** Content to be rendered in the dual list selector. */ children?: React.ReactNode; - /** Title applied to the dynamically built available options pane. */ - availableOptionsTitle?: string; - /** Options to display in the dynamically built available options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format. */ - availableOptions?: React.ReactNode[] | DualListSelectorTreeItemData[]; - /** Status message to display above the dynamically built available options pane. */ - availableOptionsStatus?: string; - /** Actions to be displayed above the dynamically built available options pane. */ - availableOptionsActions?: React.ReactNode[]; - /** Title applied to the dynamically built chosen options pane. */ - chosenOptionsTitle?: string; - /** Options to display in the dynamically built chosen options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format. */ - chosenOptions?: React.ReactNode[] | DualListSelectorTreeItemData[]; - /** Status message to display above the dynamically built chosen options pane.*/ - chosenOptionsStatus?: string; - /** Actions to be displayed above the dynamically built chosen options pane. */ - chosenOptionsActions?: React.ReactNode[]; - /** Accessible label for the dynamically built controls between the two panes. */ - controlsAriaLabel?: string; - /** Optional callback for the dynamically built add selected button */ - addSelected?: (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void; - /** Accessible label for the dynamically built add selected button */ - addSelectedAriaLabel?: string; - /** Tooltip content for the dynamically built add selected button */ - addSelectedTooltip?: React.ReactNode; - /** Additonal tooltip properties for the dynamically built add selected tooltip */ - addSelectedTooltipProps?: any; - /** Callback fired every time dynamically built options are chosen or removed */ - onListChange?: (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void; - /** Optional callback for the dynamically built add all button */ - addAll?: (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void; - /** Accessible label for the dynamically built add all button */ - addAllAriaLabel?: string; - /** Tooltip content for the dynamically built add all button */ - addAllTooltip?: React.ReactNode; - /** Additonal tooltip properties for the dynamically built add all tooltip */ - addAllTooltipProps?: any; - /** Optional callback for the dynamically built remove selected button */ - removeSelected?: (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void; - /** Accessible label for the dynamically built remove selected button */ - removeSelectedAriaLabel?: string; - /** Tooltip content for the dynamically built remove selected button */ - removeSelectedTooltip?: React.ReactNode; - /** Additonal tooltip properties for the dynamically built remove selected tooltip */ - removeSelectedTooltipProps?: any; - /** Optional callback for the dynamically built remove all button */ - removeAll?: (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void; - /** Accessible label for the dynamically built remove all button */ - removeAllAriaLabel?: string; - /** Tooltip content for the dynamically built remove all button */ - removeAllTooltip?: React.ReactNode; - /** Additonal tooltip properties for the dynamically built remove all tooltip */ - removeAllTooltipProps?: any; - /** Optional callback fired when a dynamically built option is selected */ - onOptionSelect?: ( - e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, - index: number, - isChosen: boolean, - id: string, - itemData: any, - parentData: any - ) => void; - /** Optional callback fired when a dynamically built option is checked */ - onOptionCheck?: ( - e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, - checked: boolean, - checkedId: string, - newCheckedItems: string[] - ) => void; - /** Flag indicating a search bar should be included above both the dynamically built available and chosen panes. */ - isSearchable?: boolean; - /** Accessible label for the search input on the dynamically built available options pane. */ - availableOptionsSearchAriaLabel?: string; - /** A callback for when the search input value for the dynamically built available options changes. */ - onAvailableOptionsSearchInputChanged?: (value: string, event: React.FormEvent) => void; - /** Accessible label for the search input on the dynamically built chosen options pane. */ - chosenOptionsSearchAriaLabel?: string; - /** A callback for when the search input value for the dynamically built chosen options changes. */ - onChosenOptionsSearchInputChanged?: (value: string, event: React.FormEvent) => void; - /** Optional filter function for custom filtering based on search string. Used with a dynamically built search input. */ - filterOption?: (option: React.ReactNode, input: string) => boolean; -} - -interface DualListSelectorState { - availableOptions: React.ReactNode[]; - availableOptionsSelected: number[]; - availableFilteredOptions: React.ReactNode[]; - chosenOptions: React.ReactNode[]; - chosenOptionsSelected: number[]; - chosenFilteredOptions: React.ReactNode[]; - availableTreeFilteredOptions: string[]; - availableTreeOptionsChecked: string[]; - chosenTreeOptionsChecked: string[]; - chosenTreeFilteredOptions: string[]; + /** Flag indicating whether a tree dual list selector has animations. This will always render + * nested dual list selector items rather than dynamically rendering them. This prop will be removed in + * the next breaking change release in favor of defaulting to always-rendered items. + */ + hasAnimations?: boolean; } -export class DualListSelector extends React.Component { - static displayName = 'DualListSelector'; - private addAllButtonRef = React.createRef(); - private addSelectedButtonRef = React.createRef(); - private removeSelectedButtonRef = React.createRef(); - private removeAllButtonRef = React.createRef(); - static defaultProps: PickOptional = { - children: '', - availableOptions: [] as React.ReactNode[], - availableOptionsTitle: 'Available options', - availableOptionsSearchAriaLabel: 'Available search input', - chosenOptions: [] as React.ReactNode[], - chosenOptionsTitle: 'Chosen options', - chosenOptionsSearchAriaLabel: 'Chosen search input', - id: getUniqueId('dual-list-selector'), - controlsAriaLabel: 'Selector controls', - addAllAriaLabel: 'Add all', - addSelectedAriaLabel: 'Add selected', - removeSelectedAriaLabel: 'Remove selected', - removeAllAriaLabel: 'Remove all', - isTree: false, - isDisabled: false - }; - private originalAvailableCopy = JSON.parse(JSON.stringify(this.props.availableOptions)); - private originalChosenCopy = JSON.parse(JSON.stringify(this.props.chosenOptions)); - - // If the DualListSelector uses trees, concat the two initial arrays and merge duplicate folder IDs - private mergedCopy = this.props.isTree - ? Object.values( - (this.originalAvailableCopy as DualListSelectorTreeItemData[]) - .concat(this.originalChosenCopy as DualListSelectorTreeItemData[]) - .reduce((mapObj: any, item: DualListSelectorTreeItemData) => { - const key = item.id; - if (mapObj[key]) { - // If map already has an item ID, add the dupe ID's children to the existing map - mapObj[key].children.push(...item.children); - } else { - // Else clone the item data - mapObj[key] = { ...item }; - } - return mapObj; - }, {}) - ) - : null; - - constructor(props: DualListSelectorProps) { - super(props); - this.state = { - availableOptions: [...this.props.availableOptions], - availableOptionsSelected: [], - availableFilteredOptions: null, - availableTreeFilteredOptions: null, - chosenOptions: [...this.props.chosenOptions], - chosenOptionsSelected: [], - chosenFilteredOptions: null, - chosenTreeFilteredOptions: null, - availableTreeOptionsChecked: [], - chosenTreeOptionsChecked: [] - }; - } - - componentDidUpdate() { - if ( - JSON.stringify(this.props.availableOptions) !== JSON.stringify(this.state.availableOptions) || - JSON.stringify(this.props.chosenOptions) !== JSON.stringify(this.state.chosenOptions) - ) { - this.setState({ - availableOptions: [...this.props.availableOptions], - chosenOptions: [...this.props.chosenOptions] - }); - } - } - - onFilterUpdate = (newFilteredOptions: React.ReactNode[], paneType: string, isSearchReset: boolean) => { - const { isTree } = this.props; - if (paneType === 'available') { - if (isSearchReset) { - this.setState({ - availableFilteredOptions: null, - availableTreeFilteredOptions: null - }); - return; - } - if (isTree) { - this.setState({ - availableTreeFilteredOptions: flattenTreeWithFolders(newFilteredOptions as DualListSelectorTreeItemData[]) - }); - } else { - this.setState({ - availableFilteredOptions: newFilteredOptions as React.ReactNode[] - }); - } - } else if (paneType === 'chosen') { - if (isSearchReset) { - this.setState({ - chosenFilteredOptions: null, - chosenTreeFilteredOptions: null - }); - return; - } - if (isTree) { - this.setState({ - chosenTreeFilteredOptions: flattenTreeWithFolders(newFilteredOptions as DualListSelectorTreeItemData[]) - }); - } else { - this.setState({ - chosenFilteredOptions: newFilteredOptions as React.ReactNode[] - }); - } - } - }; - - addAllVisible = () => { - this.setState(prevState => { - const itemsToRemove = [] as React.ReactNode[]; - const newAvailable = [] as React.ReactNode[]; - const movedOptions = prevState.availableFilteredOptions || prevState.availableOptions; - prevState.availableOptions.forEach(value => { - if (movedOptions.indexOf(value) !== -1) { - itemsToRemove.push(value); - } else { - newAvailable.push(value); - } - }); - - const newChosen = [...prevState.chosenOptions, ...itemsToRemove]; - this.props.addAll && this.props.addAll(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - chosenOptions: newChosen, - availableOptions: newAvailable, - chosenOptionsSelected: [], - availableOptionsSelected: [] - }; - }); - }; - - addAllTreeVisible = () => { - this.setState(prevState => { - const movedOptions = - prevState.availableTreeFilteredOptions || - flattenTreeWithFolders(prevState.availableOptions as DualListSelectorTreeItemData[]); - const newAvailable = prevState.availableOptions - .map(opt => Object.assign({}, opt)) - .filter(item => filterRestTreeItems(item as DualListSelectorTreeItemData, movedOptions)); - - const currChosen = flattenTree(prevState.chosenOptions as DualListSelectorTreeItemData[]); - const nextChosenOptions = currChosen.concat(movedOptions); - const newChosen = this.mergedCopy - .map(opt => Object.assign({}, opt)) - .filter(item => filterTreeItemsWithoutFolders(item as DualListSelectorTreeItemData, nextChosenOptions)); - - this.props.addAll && this.props.addAll(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - chosenOptions: newChosen, - chosenFilteredOptions: newChosen, - availableOptions: newAvailable, - availableFilteredOptions: newAvailable, - availableTreeOptionsChecked: [], - chosenTreeOptionsChecked: [] - }; - }); - }; - - addSelected = () => { - this.setState(prevState => { - const itemsToRemove = [] as React.ReactNode[]; - const newAvailable = [] as React.ReactNode[]; - prevState.availableOptions.forEach((value, index) => { - if (prevState.availableOptionsSelected.indexOf(index) !== -1) { - itemsToRemove.push(value); - } else { - newAvailable.push(value); - } - }); - - const newChosen = [...prevState.chosenOptions, ...itemsToRemove]; - this.props.addSelected && this.props.addSelected(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - chosenOptionsSelected: [], - availableOptionsSelected: [], - chosenOptions: newChosen, - availableOptions: newAvailable - }; - }); - }; - - addTreeSelected = () => { - this.setState(prevState => { - // Remove selected available nodes from current available nodes - const newAvailable = prevState.availableOptions - .map(opt => Object.assign({}, opt)) - .filter(item => - filterRestTreeItems(item as DualListSelectorTreeItemData, prevState.availableTreeOptionsChecked) - ); - - // Get next chosen options from current + new nodes and remap from base - const currChosen = flattenTree(prevState.chosenOptions as DualListSelectorTreeItemData[]); - const nextChosenOptions = currChosen.concat(prevState.availableTreeOptionsChecked); - const newChosen = this.mergedCopy - .map(opt => Object.assign({}, opt)) - .filter(item => filterTreeItemsWithoutFolders(item as DualListSelectorTreeItemData, nextChosenOptions)); - - this.props.addSelected && this.props.addSelected(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - availableTreeOptionsChecked: [], - chosenTreeOptionsChecked: [], - availableOptions: newAvailable, - chosenOptions: newChosen - }; - }); - }; - - removeAllVisible = () => { - this.setState(prevState => { - const itemsToRemove = [] as React.ReactNode[]; - const newChosen = [] as React.ReactNode[]; - const movedOptions = prevState.chosenFilteredOptions || prevState.chosenOptions; - prevState.chosenOptions.forEach(value => { - if (movedOptions.indexOf(value) !== -1) { - itemsToRemove.push(value); - } else { - newChosen.push(value); - } - }); - - const newAvailable = [...prevState.availableOptions, ...itemsToRemove]; - this.props.removeAll && this.props.removeAll(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - chosenOptions: newChosen, - availableOptions: newAvailable, - chosenOptionsSelected: [], - availableOptionsSelected: [] - }; - }); - }; - - removeAllTreeVisible = () => { - this.setState(prevState => { - const movedOptions = - prevState.chosenTreeFilteredOptions || - flattenTreeWithFolders(prevState.chosenOptions as DualListSelectorTreeItemData[]); - - const newChosen = prevState.chosenOptions - .map(opt => Object.assign({}, opt)) - .filter(item => filterRestTreeItems(item as DualListSelectorTreeItemData, movedOptions)); - const currAvailable = flattenTree(prevState.availableOptions as DualListSelectorTreeItemData[]); - const nextAvailableOptions = currAvailable.concat(movedOptions); - const newAvailable = this.mergedCopy - .map(opt => Object.assign({}, opt)) - .filter(item => filterTreeItemsWithoutFolders(item as DualListSelectorTreeItemData, nextAvailableOptions)); - - this.props.removeAll && this.props.removeAll(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - chosenOptions: newChosen, - availableOptions: newAvailable, - availableTreeOptionsChecked: [], - chosenTreeOptionsChecked: [] - }; - }); - }; - - removeSelected = () => { - this.setState(prevState => { - const itemsToRemove = [] as React.ReactNode[]; - const newChosen = [] as React.ReactNode[]; - prevState.chosenOptions.forEach((value, index) => { - if (prevState.chosenOptionsSelected.indexOf(index) !== -1) { - itemsToRemove.push(value); - } else { - newChosen.push(value); - } - }); - - const newAvailable = [...prevState.availableOptions, ...itemsToRemove]; - this.props.removeSelected && this.props.removeSelected(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - chosenOptionsSelected: [], - availableOptionsSelected: [], - chosenOptions: newChosen, - availableOptions: newAvailable - }; - }); - }; - - removeTreeSelected = () => { - this.setState(prevState => { - // Remove selected chosen nodes from current chosen nodes - const newChosen = prevState.chosenOptions - .map(opt => Object.assign({}, opt)) - .filter(item => filterRestTreeItems(item as DualListSelectorTreeItemData, prevState.chosenTreeOptionsChecked)); - - // Get next chosen options from current and remap from base - const currAvailable = flattenTree(prevState.availableOptions as DualListSelectorTreeItemData[]); - const nextAvailableOptions = currAvailable.concat(prevState.chosenTreeOptionsChecked); - const newAvailable = this.mergedCopy - .map(opt => Object.assign({}, opt)) - .filter(item => filterTreeItemsWithoutFolders(item as DualListSelectorTreeItemData, nextAvailableOptions)); - - this.props.removeSelected && this.props.removeSelected(newAvailable, newChosen); - this.props.onListChange && this.props.onListChange(newAvailable, newChosen); - - return { - availableTreeOptionsChecked: [], - chosenTreeOptionsChecked: [], - availableOptions: newAvailable, - chosenOptions: newChosen - }; - }); - }; - - onOptionSelect = ( - e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, - index: number, - isChosen: boolean, - /* eslint-disable @typescript-eslint/no-unused-vars */ - id?: string, - itemData?: any, - parentData?: any - /* eslint-enable @typescript-eslint/no-unused-vars */ - ) => { - this.setState(prevState => { - const originalArray = isChosen ? prevState.chosenOptionsSelected : prevState.availableOptionsSelected; - - let updatedArray = null; - if (originalArray.indexOf(index) !== -1) { - updatedArray = originalArray.filter(value => value !== index); - } else { - updatedArray = [...originalArray, index]; - } - - return { - chosenOptionsSelected: isChosen ? updatedArray : prevState.chosenOptionsSelected, - availableOptionsSelected: isChosen ? prevState.availableOptionsSelected : updatedArray - }; - }); - - this.props.onOptionSelect && this.props.onOptionSelect(e, index, isChosen, id, itemData, parentData); - }; - - isChecked = (treeItem: DualListSelectorTreeItemData, isChosen: boolean) => - isChosen - ? this.state.chosenTreeOptionsChecked.includes(treeItem.id) - : this.state.availableTreeOptionsChecked.includes(treeItem.id); - areAllDescendantsChecked = (treeItem: DualListSelectorTreeItemData, isChosen: boolean): boolean => - treeItem.children - ? treeItem.children.every(child => this.areAllDescendantsChecked(child, isChosen)) - : this.isChecked(treeItem, isChosen); - areSomeDescendantsChecked = (treeItem: DualListSelectorTreeItemData, isChosen: boolean): boolean => - treeItem.children - ? treeItem.children.some(child => this.areSomeDescendantsChecked(child, isChosen)) - : this.isChecked(treeItem, isChosen); - - mapChecked = (item: DualListSelectorTreeItemData, isChosen: boolean): DualListSelectorTreeItemData => { - const hasCheck = this.areAllDescendantsChecked(item, isChosen); - item.isChecked = false; - - if (hasCheck) { - item.isChecked = true; - } else { - const hasPartialCheck = this.areSomeDescendantsChecked(item, isChosen); - if (hasPartialCheck) { - item.isChecked = null; - } - } - - if (item.children) { - return { - ...item, - children: item.children.map(child => this.mapChecked(child, isChosen)) - }; - } - return item; - }; - - onTreeOptionCheck = ( - evt: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, - isChecked: boolean, - itemData: DualListSelectorTreeItemData, - isChosen: boolean - ) => { - const { availableOptions, availableTreeFilteredOptions, chosenOptions, chosenTreeFilteredOptions } = this.state; - let panelOptions; - if (isChosen) { - if (chosenTreeFilteredOptions) { - panelOptions = chosenOptions - .map(opt => Object.assign({}, opt)) - .filter(item => - filterTreeItemsWithoutFolders(item as DualListSelectorTreeItemData, chosenTreeFilteredOptions) - ); - } else { - panelOptions = chosenOptions; - } - } else { - if (availableTreeFilteredOptions) { - panelOptions = availableOptions - .map(opt => Object.assign({}, opt)) - .filter(item => - filterTreeItemsWithoutFolders(item as DualListSelectorTreeItemData, availableTreeFilteredOptions) - ); - } else { - panelOptions = availableOptions; - } - } - const checkedOptionTree = panelOptions - .map(opt => Object.assign({}, opt)) - .filter(item => filterTreeItems(item as DualListSelectorTreeItemData, [itemData.id])); - const flatTree = flattenTreeWithFolders(checkedOptionTree as DualListSelectorTreeItemData[]); - - const prevChecked = isChosen ? this.state.chosenTreeOptionsChecked : this.state.availableTreeOptionsChecked; - let updatedChecked = [] as string[]; - if (isChecked) { - updatedChecked = prevChecked.concat(flatTree.filter(id => !prevChecked.includes(id))); - } else { - updatedChecked = prevChecked.filter(id => !flatTree.includes(id)); - } - - this.setState( - prevState => ({ - availableTreeOptionsChecked: isChosen ? prevState.availableTreeOptionsChecked : updatedChecked, - chosenTreeOptionsChecked: isChosen ? updatedChecked : prevState.chosenTreeOptionsChecked - }), - () => { - this.props.onOptionCheck && this.props.onOptionCheck(evt, isChecked, itemData.id, updatedChecked); - } - ); - }; - - render() { - const { - availableOptionsTitle, - availableOptionsActions, - availableOptionsSearchAriaLabel, - className, - children, - chosenOptionsTitle, - chosenOptionsActions, - chosenOptionsSearchAriaLabel, - filterOption, - isSearchable, - chosenOptionsStatus, - availableOptionsStatus, - controlsAriaLabel, - addAllAriaLabel, - addSelectedAriaLabel, - removeSelectedAriaLabel, - removeAllAriaLabel, - /* eslint-disable @typescript-eslint/no-unused-vars */ - availableOptions: consumerPassedAvailableOptions, - chosenOptions: consumerPassedChosenOptions, - removeSelected, - addAll, - removeAll, - addSelected, - onListChange, - onAvailableOptionsSearchInputChanged, - onChosenOptionsSearchInputChanged, - onOptionSelect, - onOptionCheck, - id, - isTree, - isDisabled, - addAllTooltip, - addAllTooltipProps, - addSelectedTooltip, - addSelectedTooltipProps, - removeAllTooltip, - removeAllTooltipProps, - removeSelectedTooltip, - removeSelectedTooltipProps, - ...props - } = this.props; - const { - availableOptions, - chosenOptions, - chosenOptionsSelected, - availableOptionsSelected, - chosenTreeOptionsChecked, - availableTreeOptionsChecked - } = this.state; - const availableOptionsStatusToDisplay = - availableOptionsStatus || - (isTree - ? `${ - filterFolders(availableOptions as DualListSelectorTreeItemData[], availableTreeOptionsChecked).length - } of ${flattenTree(availableOptions as DualListSelectorTreeItemData[]).length} items selected` - : `${availableOptionsSelected.length} of ${availableOptions.length} items selected`); - const chosenOptionsStatusToDisplay = - chosenOptionsStatus || - (isTree - ? `${filterFolders(chosenOptions as DualListSelectorTreeItemData[], chosenTreeOptionsChecked).length} of ${ - flattenTree(chosenOptions as DualListSelectorTreeItemData[]).length - } items selected` - : `${chosenOptionsSelected.length} of ${chosenOptions.length} items selected`); - - const available = isTree - ? availableOptions.map(item => this.mapChecked(item as DualListSelectorTreeItemData, false)) - : availableOptions; - const chosen = isTree - ? chosenOptions.map(item => this.mapChecked(item as DualListSelectorTreeItemData, true)) - : chosenOptions; - - return ( - -
    - {children === '' ? ( - <> - this.onTreeOptionCheck(e, isChecked, itemData, false)} - actions={availableOptionsActions} - id={`${id}-available-pane`} - isDisabled={isDisabled} - /> - - - - - - - - - - - - - - - this.onTreeOptionCheck(e, isChecked, itemData, true)} - actions={chosenOptionsActions} - id={`${id}-chosen-pane`} - isDisabled={isDisabled} - /> - - ) : ( - children - )} -
    -
    - ); - } -} +export const DualListSelector: React.FunctionComponent = ({ + className, + children, + id, + isTree = false, + hasAnimations: hasAnimationsProp, + ...props +}: DualListSelectorProps) => { + const hasAnimations = useHasAnimations(hasAnimationsProp); + const randomId = useSSRSafeId(); + + return ( + +
    + {children} +
    +
    + ); +}; +DualListSelector.displayName = 'DualListSelector'; diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorContext.ts b/packages/react-core/src/components/DualListSelector/DualListSelectorContext.ts index 27b1ed1eff2..9ace87d2817 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorContext.ts +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorContext.ts @@ -1,10 +1,10 @@ -import * as React from 'react'; - -export const DualListSelectorContext = React.createContext<{ +import { createContext } from 'react'; +export const DualListSelectorContext = createContext<{ isTree?: boolean; -}>({ isTree: false }); + hasAnimations?: boolean; +}>({ isTree: false, hasAnimations: false }); -export const DualListSelectorListContext = React.createContext<{ +export const DualListSelectorListContext = createContext<{ setFocusedOption?: (id: string) => void; isTree?: boolean; ariaLabelledBy?: string; @@ -12,11 +12,10 @@ export const DualListSelectorListContext = React.createContext<{ displayOption?: (option: React.ReactNode) => boolean; selectedOptions?: string[] | number[]; id?: string; - onOptionSelect?: (e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, index: number, id: string) => void; options?: React.ReactNode[]; isDisabled?: boolean; }>({}); -export const DualListSelectorPaneContext = React.createContext<{ +export const DualListSelectorPaneContext = createContext<{ isChosen: boolean; }>({ isChosen: false }); diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorControl.tsx b/packages/react-core/src/components/DualListSelector/DualListSelectorControl.tsx index 924e745948f..1781fa3d664 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorControl.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorControl.tsx @@ -1,11 +1,18 @@ -import * as React from 'react'; +import { forwardRef, useRef } from 'react'; import { css } from '@patternfly/react-styles'; import { Button, ButtonVariant } from '../Button'; import { Tooltip } from '../Tooltip'; +import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; + +/** Renders an individual control button for moving selected options between each + * dual list selector pane. + */ export interface DualListSelectorControlProps extends Omit, 'onClick'> { /** Content to be rendered in the dual list selector control. */ children?: React.ReactNode; + /** Icon to be rendered in the dual list selector control. */ + icon?: React.ReactNode; /** @hide forwarded ref */ innerRef?: React.Ref; /** Flag indicating the control is disabled. */ @@ -24,7 +31,8 @@ export interface DualListSelectorControlProps extends Omit = ({ innerRef, - children = null, + children, + icon, className, 'aria-label': ariaLabel, isDisabled = true, @@ -33,9 +41,10 @@ export const DualListSelectorControlBase: React.FunctionComponent { - const ref = innerRef || React.useRef(null); + const privateRef = useRef(null); + const ref = innerRef || privateRef; return ( -
    +
    - {tooltipContent && } + {tooltipContent && }
    ); }; DualListSelectorControlBase.displayName = 'DualListSelectorControlBase'; -export const DualListSelectorControl = React.forwardRef((props: DualListSelectorControlProps, ref: React.Ref) => ( +export const DualListSelectorControl = forwardRef((props: DualListSelectorControlProps, ref: React.Ref) => ( )); diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorControlsWrapper.tsx b/packages/react-core/src/components/DualListSelector/DualListSelectorControlsWrapper.tsx index 32bf3f7cf64..3f9fcba50d7 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorControlsWrapper.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorControlsWrapper.tsx @@ -1,15 +1,17 @@ -import * as React from 'react'; +import { forwardRef, useEffect, useRef } from 'react'; import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; import { css } from '@patternfly/react-styles'; import { handleArrows } from '../../helpers'; +/** Acts as the container for the DualListSelectorControl sub-components. */ + export interface DualListSelectorControlsWrapperProps extends React.HTMLProps { - /** Anything that can be rendered inside of the wrapper. */ + /** Content to be rendered inside of the controls wrapper. */ children?: React.ReactNode; /** Additional classes added to the wrapper. */ className?: string; /** @hide Forwarded ref */ - innerRef?: React.RefObject; + innerRef?: React.RefObject; /** Accessible label for the dual list selector controls wrapper. */ 'aria-label'?: string; } @@ -21,15 +23,16 @@ export const DualListSelectorControlsWrapperBase: React.FunctionComponent { - const wrapperRef = innerRef || React.useRef(null); + const ref = useRef(null); + const wrapperRef = innerRef || ref; // Adds keyboard navigation to the dynamically built dual list selector controls. Works when controls are dynamically built // as well as when they are passed in via children. const handleKeys = (event: KeyboardEvent) => { if ( !wrapperRef.current || - (wrapperRef.current !== (event.target as HTMLElement).closest('.pf-c-dual-list-selector__controls') && - !Array.from(wrapperRef.current.getElementsByClassName('pf-c-dual-list-selector__controls')).includes( - (event.target as HTMLElement).closest('.pf-c-dual-list-selector__controls') + (wrapperRef.current !== (event.target as HTMLElement).closest(`.${styles.dualListSelectorControls}`) && + !Array.from(wrapperRef.current.getElementsByClassName(styles.dualListSelectorControls)).includes( + (event.target as HTMLElement).closest(`.${styles.dualListSelectorControls}`) )) ) { return; @@ -37,7 +40,7 @@ export const DualListSelectorControlsWrapperBase: React.FunctionComponent !el.classList.contains('pf-m-disabled') + (el) => !el.classList.contains('pf-m-disabled') ); const activeElement = document.activeElement; handleArrows( @@ -52,11 +55,12 @@ export const DualListSelectorControlsWrapperBase: React.FunctionComponent { + useEffect(() => { window.addEventListener('keydown', handleKeys); return () => { window.removeEventListener('keydown', handleKeys); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [wrapperRef.current]); return ( @@ -74,9 +78,9 @@ export const DualListSelectorControlsWrapperBase: React.FunctionComponent) => ( - } {...props} /> + } role="group" {...props} /> ) ); diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorList.tsx b/packages/react-core/src/components/DualListSelector/DualListSelectorList.tsx index c1feaafaa92..96287bdc7b8 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorList.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorList.tsx @@ -1,44 +1,40 @@ +import { forwardRef, useContext } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; import { DualListSelectorListItem } from './DualListSelectorListItem'; -import * as React from 'react'; import { DualListSelectorListContext } from './DualListSelectorContext'; +/** Acts as the container for DualListSelectorListItem sub-components. */ + export interface DualListSelectorListProps extends React.HTMLProps { + /** Content rendered inside the dual list selector list. */ children?: React.ReactNode; + /** @hide forwarded ref */ + innerRef?: React.RefObject; } -export const DualListSelectorList: React.FunctionComponent = ({ +export const DualListSelectorListBase: React.FunctionComponent = ({ children, + innerRef, ...props }: DualListSelectorListProps) => { - const { - setFocusedOption, - isTree, - ariaLabelledBy, - focusedOption, - displayOption, - selectedOptions, - id, - onOptionSelect, - options, - isDisabled - } = React.useContext(DualListSelectorListContext); + const { isTree, ariaLabelledBy, focusedOption, displayOption, selectedOptions, id, options, isDisabled } = + useContext(DualListSelectorListContext); - // only called when options are passed via options prop - const onOptionClick = (e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, index: number, id: string) => { - setFocusedOption(id); - onOptionSelect(e, index, id); - }; + const hasOptions = () => + options.length !== 0 || (children !== undefined && (children as React.ReactNode[]).length !== 0); return (
      {options.length === 0 @@ -50,7 +46,6 @@ export const DualListSelectorList: React.FunctionComponent onOptionClick(e, index, id)} orderIndex={index} isDisabled={isDisabled} > @@ -63,4 +58,10 @@ export const DualListSelectorList: React.FunctionComponent ); }; +DualListSelectorListBase.displayName = 'DualListSelectorListBase'; + +export const DualListSelectorList = forwardRef((props: DualListSelectorListProps, ref: React.Ref) => ( + } {...props} /> +)); + DualListSelectorList.displayName = 'DualListSelectorList'; diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorListItem.tsx b/packages/react-core/src/components/DualListSelector/DualListSelectorListItem.tsx index 2fb101cda0a..c994ffc07ef 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorListItem.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorListItem.tsx @@ -1,11 +1,15 @@ -import * as React from 'react'; +import { forwardRef, useContext, useRef } from 'react'; import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; import { css } from '@patternfly/react-styles'; -import { getUniqueId } from '../../helpers'; +import { useSSRSafeId } from '../../helpers'; import GripVerticalIcon from '@patternfly/react-icons/dist/esm/icons/grip-vertical-icon'; import { Button, ButtonVariant } from '../Button'; import { DualListSelectorListContext } from './DualListSelectorContext'; +/** Creates an individual option that can be selected and moved between the + * dual list selector panes. This is contained within the DualListSelectorList sub-component. + */ + export interface DualListSelectorListItemProps extends React.HTMLProps { /** Content rendered inside the dual list selector. */ children?: React.ReactNode; @@ -13,19 +17,19 @@ export interface DualListSelectorListItemProps extends React.HTMLProps void; + /** Callback fired when an option is selected. */ + onOptionSelect?: (event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, id?: string) => void; /** ID of the option. */ id?: string; /** @hide Internal field used to keep track of order of unfiltered options. */ orderIndex?: number; /** @hide Forwarded ref */ - innerRef?: React.RefObject; - /** Flag indicating this item is draggable for reordring */ + innerRef?: React.RefObject; + /** Flag indicating this item is draggable for reordering. */ isDraggable?: boolean; - /** Accessible label for the draggable button on draggable list items */ + /** Accessible label for the draggable button on draggable list items. */ draggableButtonAriaLabel?: string; - /** Flag indicating if the dual list selector is in a disabled state */ + /** Flag indicating if the dual list selector is in a disabled state. */ isDisabled?: boolean; } @@ -34,16 +38,20 @@ export const DualListSelectorListItemBase: React.FunctionComponent { - const ref = innerRef || React.useRef(null); - const { setFocusedOption } = React.useContext(DualListSelectorListContext); + const generatedId = useSSRSafeId('dual-list-selector-list-item'); + const id = idProp ?? generatedId; + const privateRef = useRef(null); + const ref = innerRef || privateRef; + const { setFocusedOption } = useContext(DualListSelectorListContext); return (
    • {isDraggable && !isDisabled && (
      - + {/** TODO once keyboard accessibility is enabled, remove `component=span` + and add `aria-label={draggableButtonAriaLabel}` */} +
      )} @@ -89,7 +101,7 @@ export const DualListSelectorListItemBase: React.FunctionComponent) => ( } {...props} /> ) diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorListWrapper.tsx b/packages/react-core/src/components/DualListSelector/DualListSelectorListWrapper.tsx index 49e1acf7535..e4f8bcb73f5 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorListWrapper.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorListWrapper.tsx @@ -1,28 +1,26 @@ -import * as React from 'react'; +import { forwardRef, useContext, useEffect, useRef, useState } from 'react'; import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; import { css } from '@patternfly/react-styles'; -import { getUniqueId, handleArrows } from '../../helpers'; +import { handleArrows, useSSRSafeId } from '../../helpers'; import { DualListSelectorList } from './DualListSelectorList'; import { DualListSelectorContext, DualListSelectorListContext } from './DualListSelectorContext'; export interface DualListSelectorListWrapperProps extends React.HTMLProps { /** Additional classes applied to the dual list selector. */ className?: string; - /** Anything that can be rendered inside of the list */ + /** Anything that can be rendered inside of the list. */ children?: React.ReactNode; - /** Id of the dual list selector list */ + /** ID of the dual list selector list. */ id?: string; - /** Accessibly label for the list */ + /** Accessibly label for the list. */ 'aria-labelledby': string; /** @hide forwarded ref */ - innerRef?: React.RefObject; + innerRef?: React.RefObject; /** @hide Options to list in the pane. */ options?: React.ReactNode[]; /** @hide Options currently selected in the pane. */ selectedOptions?: string[] | number[]; - /** @hide Callback for when an option is selected. Optionally used only when options prop is provided. */ - onOptionSelect?: (e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, index: number, id: string) => void; - /** @hide Function to determine if an option should be displayed depending on a dynamically built filter value */ + /** @hide Function to determine if an option should be displayed depending on a custom filter value. */ displayOption?: (option: React.ReactNode) => boolean; /** Flag indicating whether the component is disabled. */ isDisabled?: boolean; @@ -35,52 +33,56 @@ export const DualListSelectorListWrapperBase: React.FunctionComponent { - const [focusedOption, setFocusedOption] = React.useState(''); - const menuRef = innerRef || React.useRef(null); - const { isTree } = React.useContext(DualListSelectorContext); + const generatedId = useSSRSafeId('dual-list-selector-list'); + const id = idProp ?? generatedId; + const [focusedOption, setFocusedOption] = useState(''); + const ref = useRef(null); + const menuRef = innerRef || ref; + const { isTree } = useContext(DualListSelectorContext); - // sets up keyboard focus handling for the dual list selector menu child of the pane. This keyboard - // handling is applied whether the pane is dynamically built or passed via the children prop. + // Sets up keyboard focus handling for the dual list selector menu child of the pane. const handleKeys = (event: KeyboardEvent) => { if ( !menuRef.current || - (menuRef.current !== (event.target as HTMLElement).closest('.pf-c-dual-list-selector__menu') && - !Array.from(menuRef.current.getElementsByClassName('pf-c-dual-list-selector__menu')).includes( - (event.target as HTMLElement).closest('.pf-c-dual-list-selector__menu') + (menuRef.current !== (event.target as HTMLElement).closest(`.${styles.dualListSelectorMenu}`) && + !Array.from(menuRef.current.getElementsByClassName(styles.dualListSelectorMenu)).includes( + (event.target as HTMLElement).closest(`.${styles.dualListSelectorMenu}`) )) ) { return; } event.stopImmediatePropagation(); const validOptions = isTree - ? (Array.from( - menuRef.current.querySelectorAll( - '.pf-c-dual-list-selector__item-toggle, .pf-c-dual-list-selector__item-check > input' - ) - ) as Element[]) + ? ( + Array.from( + menuRef.current.querySelectorAll( + `.${styles.dualListSelectorItemToggle}, .${styles.dualListSelectorItemCheck} > input` + ) + ) as Element[] + ).filter((item) => !item.closest(`.${styles.dualListSelectorList}[inert]`)) : (Array.from(menuRef.current.getElementsByTagName('LI')) as Element[]).filter( - el => !el.classList.contains('pf-m-disabled') + (el) => !el.classList.contains('pf-m-disabled') ); + const activeElement = document.activeElement; handleArrows( event, validOptions, (element: Element) => activeElement.contains(element), (element: Element) => { - if (element.classList.contains('.pf-c-dual-list-selector__list-item')) { + if (element.classList.contains(`.${styles.dualListSelectorListItem}`)) { setFocusedOption(element.id); } else { - setFocusedOption(element.closest('.pf-c-dual-list-selector__list-item').id); + setFocusedOption(element.closest(`.${styles.dualListSelectorListItem}`).id); } return element; }, - ['.pf-c-dual-list-selector__item-toggle', '.pf-c-dual-list-selector__item-check > input'], + [`.${styles.dualListSelectorItemToggle}`, `.${styles.dualListSelectorItemCheck} > input`], undefined, false, false, @@ -88,11 +90,12 @@ export const DualListSelectorListWrapperBase: React.FunctionComponent { + useEffect(() => { window.addEventListener('keydown', handleKeys); return () => { window.removeEventListener('keydown', handleKeys); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [menuRef.current]); return ( @@ -107,7 +110,6 @@ export const DualListSelectorListWrapperBase: React.FunctionComponent @@ -118,7 +120,7 @@ export const DualListSelectorListWrapperBase: React.FunctionComponent) => ( } {...props} /> ) diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorPane.tsx b/packages/react-core/src/components/DualListSelector/DualListSelectorPane.tsx index e93dfb5b63c..c7b9a8f98a6 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorPane.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorPane.tsx @@ -1,14 +1,17 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; import { css } from '@patternfly/react-styles'; -import formStyles from '@patternfly/react-styles/css/components/FormControl/form-control'; -import { DualListSelectorTree, DualListSelectorTreeItemData } from './DualListSelectorTree'; -import { getUniqueId } from '../../helpers'; +import { useSSRSafeId } from '../../helpers'; import { DualListSelectorListWrapper } from './DualListSelectorListWrapper'; -import { DualListSelectorContext, DualListSelectorPaneContext } from './DualListSelectorContext'; -import { DualListSelectorList } from './DualListSelectorList'; +import { DualListSelectorPaneContext } from './DualListSelectorContext'; +import { SearchInput } from '../SearchInput'; +import cssMenuMinHeight from '@patternfly/react-tokens/dist/esm/c_dual_list_selector__menu_MinHeight'; -export interface DualListSelectorPaneProps { +/** Acts as the container for a list of options that are either available or chosen, + * depending on the pane type (available or chosen). A search input and other actions, + * such as sorting, can also be passed into this sub-component. + */ + +export interface DualListSelectorPaneProps extends Omit, 'title'> { /** Additional classes applied to the dual list selector pane. */ className?: string; /** A dual list selector list or dual list selector tree to be rendered in the pane. */ @@ -23,41 +26,14 @@ export interface DualListSelectorPaneProps { searchInput?: React.ReactNode; /** Actions to place above the pane. */ actions?: React.ReactNode[]; - /** Id of the pane. */ + /** ID of the pane. */ id?: string; - /** @hide Options to list in the pane. */ - options?: React.ReactNode[]; - /** @hide Options currently selected in the pane. */ - selectedOptions?: string[] | number[]; - /** @hide Callback for when an option is selected. Optionally used only when options prop is provided. */ - onOptionSelect?: ( - e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, - index: number, - isChosen: boolean, - id?: string, - itemData?: any, - parentData?: any - ) => void; - /** @hide Callback for when a tree option is checked. Optionally used only when options prop is provided. */ - onOptionCheck?: ( - evt: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, - isChecked: boolean, - itemData: DualListSelectorTreeItemData - ) => void; - /** @hide Flag indicating a dynamically built search bar should be included above the pane. */ - isSearchable?: boolean; /** Flag indicating whether the component is disabled. */ isDisabled?: boolean; /** Callback for search input. To be used when isSearchable is true. */ onSearch?: (event: React.ChangeEvent) => void; - /** @hide A callback for when the search input value for changes. To be used when isSearchable is true. */ - onSearchInputChanged?: (value: string, event: React.FormEvent) => void; - /** @hide Filter function for custom filtering based on search string. To be used when isSearchable is true. */ - filterOption?: (option: React.ReactNode, input: string) => boolean; - /** @hide Accessible label for the search input. To be used when isSearchable is true. */ - searchInputAriaLabel?: string; - /** @hide Callback for updating the filtered options in DualListSelector. To be used when isSearchable is true. */ - onFilterUpdate?: (newFilteredOptions: React.ReactNode[], paneType: string, isSearchReset: boolean) => void; + /** Minimum height of the list of options rendered in the pane. **/ + listMinHeight?: string; } export const DualListSelectorPane: React.FunctionComponent = ({ @@ -67,75 +43,14 @@ export const DualListSelectorPane: React.FunctionComponent { - const [input, setInput] = React.useState(''); - const { isTree } = React.useContext(DualListSelectorContext); - - // only called when search input is dynamically built - const onChange = (e: React.ChangeEvent) => { - const newValue = e.target.value; - let filtered; - if (isTree) { - filtered = (options as DualListSelectorTreeItemData[]) - .map(opt => Object.assign({}, opt)) - .filter(item => filterInput(item as DualListSelectorTreeItemData, newValue)); - } else { - filtered = options.filter(option => { - if (displayOption(option)) { - return option; - } - }); - } - onFilterUpdate(filtered, isChosen ? 'chosen' : 'available', newValue === ''); - - if (onSearchInputChanged) { - onSearchInputChanged(newValue, e); - } - setInput(newValue); - }; - - // only called when options are passed via options prop and isTree === true - const filterInput = (item: DualListSelectorTreeItemData, input: string): boolean => { - if (filterOption) { - return filterOption(item, input); - } else { - if (item.text.toLowerCase().includes(input.toLowerCase()) || input === '') { - return true; - } - } - if (item.children) { - return ( - (item.children = item.children.map(opt => Object.assign({}, opt)).filter(child => filterInput(child, input))) - .length > 0 - ); - } - }; - - // only called when options are passed via options prop and isTree === false - const displayOption = (option: React.ReactNode) => { - if (filterOption) { - return filterOption(option, input); - } else { - return option - .toString() - .toLowerCase() - .includes(input.toLowerCase()); - } - }; - + const generatedId = useSSRSafeId('dual-list-selector-pane'); + const id = idProp ?? generatedId; return (
      {title && (
      -
      +
      {title}
      )} - {(actions || searchInput || isSearchable) && ( + {(actions || searchInput) && (
      - {(isSearchable || searchInput) && ( + {searchInput && (
      - {searchInput ? ( - searchInput - ) : ( - - )} + {searchInput ? searchInput : }
      )} {actions &&
      {actions}
      } @@ -176,45 +81,15 @@ export const DualListSelectorPane: React.FunctionComponent )} - {!isTree && ( - onOptionSelect(e, index, isChosen, id)} - displayOption={displayOption} - id={`${id}-list`} - isDisabled={isDisabled} - > - {children} - - )} - {isTree && ( - - {options.length > 0 ? ( - - Object.assign({}, opt)) - .filter(item => filterInput(item as DualListSelectorTreeItemData, input)) - : (options as DualListSelectorTreeItemData[]) - } - onOptionCheck={onOptionCheck} - id={`${id}-tree`} - isDisabled={isDisabled} - /> - - ) : ( - children - )} - - )} + + {children} +
      ); diff --git a/packages/react-core/src/components/DualListSelector/DualListSelectorTree.tsx b/packages/react-core/src/components/DualListSelector/DualListSelectorTree.tsx index df7d1f889b7..e2a8bf57031 100644 --- a/packages/react-core/src/components/DualListSelector/DualListSelectorTree.tsx +++ b/packages/react-core/src/components/DualListSelector/DualListSelectorTree.tsx @@ -1,6 +1,7 @@ -import * as React from 'react'; +import { useContext } from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; +import { DualListSelectorContext } from './DualListSelectorContext'; import { DualListSelectorTreeItem } from './DualListSelectorTreeItem'; export interface DualListSelectorTreeItemData { @@ -10,44 +11,49 @@ export interface DualListSelectorTreeItemData { className?: string; /** Flag indicating this option is expanded by default. */ defaultExpanded?: boolean; - /** Flag indicating this option has a badge */ + /** Flag indicating this option has a badge. */ hasBadge?: boolean; - /** Callback fired when an option is checked */ + /** Callback fired when an option is checked. */ onOptionCheck?: ( event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, isChecked: boolean, isChosen: boolean, itemData: DualListSelectorTreeItemData ) => void; - /** ID of the option */ + /** ID of the option. */ id: string; - /** Text of the option */ + /** Text of the option. */ text: string; - /** Parent id of an option */ + /** Parent ID of an option. */ parentId?: string; - /** Checked state of the option */ + /** Checked state of the option. */ isChecked: boolean; - /** Additional properties to pass to the option checkbox */ + /** Additional properties to pass to the option checkbox. */ checkProps?: any; - /** Additional properties to pass to the option badge */ + /** Additional properties to pass to the option badge. */ badgeProps?: any; /** Flag indicating whether the component is disabled. */ isDisabled?: boolean; } -export interface DualListSelectorTreeProps { - /** Data of the tree view */ +/** Used in place of the DualListSelectorListItem sub-component when building a + * composable dual list selector with a tree. + */ + +export interface DualListSelectorTreeProps extends Omit, 'data'> { + /** Data of the tree view. */ data: DualListSelectorTreeItemData[] | (() => DualListSelectorTreeItemData[]); - /** ID of the tree view */ + /** ID of the tree view. */ id?: string; - /** @hide Flag indicating if the list is nested */ + /** @hide Flag indicating if the list is nested. */ isNested?: boolean; - /** Flag indicating if all options should have badges */ + /** Flag indicating if all options should have badges. */ hasBadges?: boolean; - /** Sets the default expanded behavior */ + /** Sets the default expanded behavior. */ defaultAllExpanded?: boolean; - /** Callback fired when an option is checked */ + /** Flag indicating if the dual list selector tree is in the disabled state. */ isDisabled?: boolean; + /** Callback fired when an option is checked. */ onOptionCheck?: ( event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, isChecked: boolean, @@ -64,11 +70,13 @@ export const DualListSelectorTree: React.FunctionComponent { + const { hasAnimations } = useContext(DualListSelectorContext); const dataToRender = typeof data === 'function' ? data() : data; - const tree = dataToRender.map(item => ( + const tree = dataToRender.map((item) => ( { /** Content rendered inside the dual list selector. */ @@ -14,30 +15,35 @@ export interface DualListSelectorTreeItemProps extends React.HTMLProps | React.KeyboardEvent, isChecked: boolean, itemData: DualListSelectorTreeItemData ) => void; - /** ID of the option */ + /** ID of the option. */ id: string; - /** Text of the option */ + /** Text of the option. */ text: string; /** Flag indicating if this open is checked. */ isChecked?: boolean; - /** Additional properties to pass to the option checkbox */ + /** Additional properties to pass to the option checkbox. */ checkProps?: any; - /** Additional properties to pass to the option badge */ + /** Additional properties to pass to the option badge. */ badgeProps?: any; - /** Raw data of the option */ + /** Raw data of the option. */ itemData?: DualListSelectorTreeItemData; /** Flag indicating whether the component is disabled. */ isDisabled?: boolean; /** Flag indicating the DualListSelector tree should utilize memoization to help render large data sets. */ useMemo?: boolean; + /** Flag indicating whether a tree dual list selector has animations. This will always render + * nested dual list selector items rather than dynamically rendering them. This prop will be removed in + * the next breaking change release in favor of defaulting to always-rendered items. + */ + hasAnimations?: boolean; } const DualListSelectorTreeItemBase: React.FunctionComponent = ({ @@ -53,18 +59,29 @@ const DualListSelectorTreeItemBase: React.FunctionComponent { - const ref = React.useRef(null); - const [isExpanded, setIsExpanded] = React.useState(defaultExpanded || false); - const { setFocusedOption } = React.useContext(DualListSelectorListContext); + const ref = useRef(null); + const [isExpanded, setIsExpanded] = useState(defaultExpanded || false); + const { setFocusedOption } = useContext(DualListSelectorListContext); + const hasAnimations = useHasAnimations(hasAnimationsProp); - React.useEffect(() => { + useEffect(() => { setIsExpanded(defaultExpanded); }, [defaultExpanded]); + const clonedChildren = Children.map( + children, + (child) => + isValidElement(child) && + cloneElement(child as React.ReactElement, { + inert: isExpanded ? undefined : '' + }) + ); + return (
    • { + : (evt) => { onOptionCheck && onOptionCheck(evt, !isChecked, itemData); setFocusedOption(id); } @@ -104,7 +121,7 @@ const DualListSelectorTreeItemBase: React.FunctionComponent { + onClick={(e) => { if (children) { setIsExpanded(!isExpanded); } @@ -119,7 +136,7 @@ const DualListSelectorTreeItemBase: React.FunctionComponent - +
    )} @@ -138,7 +155,9 @@ const DualListSelectorTreeItemBase: React.FunctionComponent elem && (elem.indeterminate = isChecked === null)} + ref={(elem) => { + elem && (elem.indeterminate = isChecked === null); + }} checked={isChecked || false} tabIndex={-1} {...checkProps} @@ -148,18 +167,18 @@ const DualListSelectorTreeItemBase: React.FunctionComponent{text} {hasBadge && children && ( - {flattenTree((children as React.ReactElement).props.data).length} + {flattenTree((children as React.ReactElement).props.data).length} )} - {isExpanded && children} + {(isExpanded || hasAnimations) && clonedChildren} ); }; -export const DualListSelectorTreeItem = React.memo(DualListSelectorTreeItemBase, (prevProps, nextProps) => { +export const DualListSelectorTreeItem = memo(DualListSelectorTreeItemBase, (prevProps, nextProps) => { if (!nextProps.useMemo) { return false; } diff --git a/packages/react-core/src/components/DualListSelector/__tests__/DualListSelector.test.tsx b/packages/react-core/src/components/DualListSelector/__tests__/DualListSelector.test.tsx index 2678794d0e4..3d3601fe8a1 100644 --- a/packages/react-core/src/components/DualListSelector/__tests__/DualListSelector.test.tsx +++ b/packages/react-core/src/components/DualListSelector/__tests__/DualListSelector.test.tsx @@ -1,61 +1,83 @@ -import { mount } from 'enzyme'; -import { DualListSelector } from '../../DualListSelector'; -import React from 'react'; +import { render, screen } from '@testing-library/react'; +import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; +import { DualListSelector } from '../DualListSelector'; +import { DualListSelectorPane } from '../DualListSelectorPane'; +import { SearchInput } from '../../SearchInput'; +import { AnimationsProvider } from '../../../helpers/AnimationsProvider'; +// The following tests can be removed as part of https://github.com/patternfly/patternfly-react/issues/11838 +describe('Opt-in animations', () => { + test(`Does not render with class ${styles.modifiers.animateExpand} by default`, () => { + render(); + + expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand); + }); + + test(`Does not render with class ${styles.modifiers.animateExpand} when hasAnimations is true and isTree is false`, () => { + render(); + + expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand); + }); + + test(`Does not render with class ${styles.modifiers.animateExpand} by default when isTree is true`, () => { + render(); + + expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand); + }); + + test(`Renders with class ${styles.modifiers.animateExpand} when both isTree and hasAnimations are true`, () => { + render(); + + expect(screen.getByTestId('test-id')).toHaveClass(styles.modifiers.animateExpand); + }); + + // Animation context tests + test('respects AnimationsProvider context when no local hasAnimations prop', () => { + render( + + + + ); + + expect(screen.getByTestId('test-id')).toHaveClass(styles.modifiers.animateExpand); + }); + + test('local hasAnimations prop takes precedence over context', () => { + render( + + + + ); + + expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand); + }); + + test('works without AnimationsProvider (backward compatibility)', () => { + render(); + + expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand); + }); +}); + +// Following tests should be moved to a separate DualListSelectorPane test file describe('DualListSelector', () => { test('basic', () => { - const view = mount(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); test('with search inputs', () => { - const view = mount(); - expect(view).toMatchSnapshot(); + const { asFragment } = render(} />); + expect(asFragment()).toMatchSnapshot(); }); test('with custom status', () => { - const view = mount( - - ); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); test('basic with disabled controls', () => { - const view = mount(); - expect(view).toMatchSnapshot(); - }); - - test('with tree', () => { - const view = mount( - - ); - expect(view).toMatchSnapshot(); - }); - - test('with actions', () => { - const view = mount( - TestNode1]} - chosenOptionsActions={[TestNode2]} - id="fourthTest" - /> - ); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); }); diff --git a/packages/react-core/src/components/DualListSelector/__tests__/DualListSelectorTreeItem.test.tsx b/packages/react-core/src/components/DualListSelector/__tests__/DualListSelectorTreeItem.test.tsx new file mode 100644 index 00000000000..87ec2df53da --- /dev/null +++ b/packages/react-core/src/components/DualListSelector/__tests__/DualListSelectorTreeItem.test.tsx @@ -0,0 +1,55 @@ +import { render, screen } from '@testing-library/react'; +import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector'; +import { DualListSelectorTreeItem } from '../DualListSelectorTreeItem'; + +// The following tests checking for children to not be/to be rendered will need to be refactored +// as part of https://github.com/patternfly/patternfly-react/issues/11838 +test('Does not render children by default', () => { + render( + +
    Children content
    +
    + ); + + expect(screen.queryByText('Children content')).not.toBeInTheDocument(); +}); + +test('Renders children when defaultExpanded is true', () => { + render( + +
    Children content
    +
    + ); + + expect(screen.getByText('Children content')).toBeVisible(); +}); + +test('Renders children when hasAnimations is true', () => { + render( + +
    Children content
    +
    + ); + + expect(screen.getByText('Children content')).toBeVisible(); +}); + +test('Renders children with inert attribute by default when hasAnimations is true', () => { + render( + +
    Children content
    +
    + ); + + expect(screen.getByText('Children content')).toHaveAttribute('inert', ''); +}); + +test('Does not render children with inert attribute when hasAnimations and defaultExpanded are true', () => { + render( + +
    Children content
    +
    + ); + + expect(screen.getByText('Children content')).not.toHaveAttribute('inert'); +}); diff --git a/packages/react-core/src/components/DualListSelector/__tests__/__snapshots__/DualListSelector.test.tsx.snap b/packages/react-core/src/components/DualListSelector/__tests__/__snapshots__/DualListSelector.test.tsx.snap index 6a7c0564a4e..f9529ee933f 100644 --- a/packages/react-core/src/components/DualListSelector/__tests__/__snapshots__/DualListSelector.test.tsx.snap +++ b/packages/react-core/src/components/DualListSelector/__tests__/__snapshots__/DualListSelector.test.tsx.snap @@ -1,5313 +1,134 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DualListSelector basic 1`] = ` - +
    - -
    -
    -
    -
    - Available options -
    -
    -
    -
    -
    - 0 of 2 items selected -
    -
    - - -
    - -
      - - -
    • -
      - - - - Option 1 - - - -
      -
    • -
      -
      - - -
    • -
      - - - - Option 2 - - - -
      -
    • -
      -
      -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={false} - onClick={[Function]} - > -
    - , - } - } - isDisabled={false} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Chosen options -
    -
    -
    -
    -
    - 0 of 0 items selected -
    -
    - - -
    - -
      - -
    -
    -
    -
    -
    +
    +
      +
    -
    + `; exports[`DualListSelector basic with disabled controls 1`] = ` - +
    - -
    -
    -
    -
    - Available options -
    -
    -
    -
    -
    - 0 of 2 items selected -
    -
    - - -
    - -
      - - -
    • -
      - - - - Option 1 - - - -
      -
    • -
      -
      - - -
    • -
      - - - - Option 2 - - - -
      -
    • -
      -
      -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Chosen options -
    -
    -
    -
    -
    - 0 of 0 items selected -
    -
    - - -
    - -
      - -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`DualListSelector with actions 1`] = ` - - TestNode1 - , - ] - } - availableOptionsSearchAriaLabel="Available search input" - availableOptionsTitle="Available options" - chosenOptions={ - Array [ - "Option 3", - "Option 4", - ] - } - chosenOptionsActions={ - Array [ - - TestNode2 - , - ] - } - chosenOptionsSearchAriaLabel="Chosen search input" - chosenOptionsTitle="Chosen options" - controlsAriaLabel="Selector controls" - id="fourthTest" - isDisabled={false} - isTree={false} - removeAllAriaLabel="Remove all" - removeSelectedAriaLabel="Remove selected" -> -
    - - TestNode1 - , - ] - } - id="fourthTest-available-pane" - isDisabled={false} - onFilterUpdate={[Function]} - onOptionCheck={[Function]} - onOptionSelect={[Function]} - options={ - Array [ - "Option 1", - "Option 2", - ] - } - searchInputAriaLabel="Available search input" - selectedOptions={Array []} - status="0 of 2 items selected" - title="Available options" - > -
    -
    -
    -
    - Available options -
    -
    -
    -
    -
    - - TestNode1 - -
    -
    -
    -
    - 0 of 2 items selected -
    -
    - - -
    - -
      - - -
    • -
      - - - - Option 1 - - - -
      -
    • -
      -
      - - -
    • -
      - - - - Option 2 - - - -
      -
    • -
      -
      -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={false} - onClick={[Function]} - > -
    - , - } - } - isDisabled={false} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={false} - onClick={[Function]} - > -
    - , - } - } - isDisabled={false} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    -
    -
    -
    - - TestNode2 - , - ] - } - id="fourthTest-chosen-pane" - isChosen={true} - isDisabled={false} - onFilterUpdate={[Function]} - onOptionCheck={[Function]} - onOptionSelect={[Function]} - options={ - Array [ - "Option 3", - "Option 4", - ] - } - searchInputAriaLabel="Chosen search input" - selectedOptions={Array []} - status="0 of 2 items selected" - title="Chosen options" - > -
    -
    -
    -
    - Chosen options -
    -
    -
    -
    -
    - - TestNode2 - -
    -
    -
    -
    - 0 of 2 items selected -
    -
    - - -
    - -
      - - -
    • -
      - - - - Option 3 - - - -
      -
    • -
      -
      - - -
    • -
      - - - - Option 4 - - - -
      -
    • -
      -
      -
    -
    -
    -
    -
    -
    -
    +
    +
      +
    -
    + `; exports[`DualListSelector with custom status 1`] = ` - +
    - -
    -
    -
    -
    - Available options -
    -
    -
    -
    -
    - Test status1 -
    -
    - - -
    - -
      - - -
    • -
      - - - - Option 1 - - - -
      -
    • -
      -
      - - -
    • -
      - - - - Option 2 - - - -
      -
    • -
      -
      -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={false} - onClick={[Function]} - > -
    - , - } - } - isDisabled={false} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - Chosen options -
    -
    -
    -
    -
    - Test status2 -
    -
    - - -
    - -
      - -
    -
    -
    + Test status1
    -
    +
    +
    +
      +
    -
    + `; exports[`DualListSelector with search inputs 1`] = ` - +
    -
    -
    -
    - Available options -
    -
    -
    -
    -
    - -
    -
    -
    - 0 of 2 items selected -
    -
    - - -
    - -
      - - -
    • -
      - - - - Option 1 - - - -
      -
    • -
      -
      - - -
    • -
      - - - - Option 2 - - - -
      -
    • -
      -
      -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={false} - onClick={[Function]} - > -
    - , - } - } - isDisabled={false} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Chosen options -
    -
    -
    -
    -
    - -
    -
    -
    -
    - 0 of 0 items selected -
    -
    - - -
    - -
      - -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`DualListSelector with tree 1`] = ` - -
    - -
    -
    -
    -
    - Available options -
    -
    -
    -
    -
    - Test status1 -
    -
    - - -
    - -
      - - -
    • -
      -
      - -
      - - - - - - - -
      - - - - - Opt1 - -
      -
      -
      - -
        - -
      • -
        -
        - - - - - - Opt3 - - -
        -
        -
      • -
        -
      -
      -
    • -
      - -
    • -
      -
      - - - - - - Opt2 - - -
      -
      -
    • -
      -
      -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={false} - onClick={[Function]} - > -
    - , - } - } - isDisabled={false} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    - - - - , - } - } - isDisabled={true} - onClick={[Function]} - > -
    - , - } - } - isDisabled={true} - onClick={[Function]} - tabIndex={-1} - variant="plain" - > - - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Chosen options -
    -
    -
    -
    -
    - Test status2 + + + + + +
    - - -
    - -
      - -
    -
    -
    -
    +
    +
    +
      +
    -
    + `; diff --git a/packages/react-core/src/components/DualListSelector/examples/ComposableTree.tsx b/packages/react-core/src/components/DualListSelector/examples/ComposableTree.tsx deleted file mode 100644 index 1622059291b..00000000000 --- a/packages/react-core/src/components/DualListSelector/examples/ComposableTree.tsx +++ /dev/null @@ -1,345 +0,0 @@ -import React from 'react'; -import { - DualListSelector, - DualListSelectorPane, - DualListSelectorList, - DualListSelectorControlsWrapper, - DualListSelectorControl, - DualListSelectorTree, - DualListSelectorTreeItemData, - SearchInput -} from '@patternfly/react-core'; -import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; -import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; -import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; - -interface FoodNode { - id: string; - text: string; - children?: FoodNode[]; -} - -interface ExampleProps { - data: FoodNode[]; -} - -export const ComposableDualListSelectorTree: React.FunctionComponent = ({ data }: ExampleProps) => { - const [checkedLeafIds, setCheckedLeafIds] = React.useState([]); - const [chosenLeafIds, setChosenLeafIds] = React.useState(['beans', 'beef', 'chicken', 'tofu']); - const [chosenFilter, setChosenFilter] = React.useState(''); - const [availableFilter, setAvailableFilter] = React.useState(''); - let hiddenChosen: string[] = []; - let hiddenAvailable: string[] = []; - - // helper function to build memoized lists - const buildTextById = (node: FoodNode): { [key: string]: string } => { - let textById = {}; - if (!node) { - return textById; - } - textById[node.id] = node.text; - if (node.children) { - node.children.forEach(child => { - textById = { ...textById, ...buildTextById(child) }; - }); - } - return textById; - }; - - // helper function to build memoized lists - const getDescendantLeafIds = (node: FoodNode): string[] => { - if (!node.children || !node.children.length) { - return [node.id]; - } else { - let childrenIds = []; - node.children.forEach(child => { - childrenIds = [...childrenIds, ...getDescendantLeafIds(child)]; - }); - return childrenIds; - } - }; - - // helper function to build memoized lists - const getLeavesById = (node: FoodNode): { [key: string]: string[] } => { - let leavesById = {}; - if (!node.children || !node.children.length) { - leavesById[node.id] = [node.id]; - } else { - node.children.forEach(child => { - leavesById[node.id] = getDescendantLeafIds(node); - leavesById = { ...leavesById, ...getLeavesById(child) }; - }); - } - return leavesById; - }; - - // Builds a map of child leaf nodes by node id - memoized so that it only rebuilds the list if the data changes. - const { memoizedLeavesById, memoizedAllLeaves, memoizedNodeText } = React.useMemo(() => { - let leavesById = {}; - let allLeaves = []; - let nodeTexts = {}; - data.forEach(foodNode => { - nodeTexts = { ...nodeTexts, ...buildTextById(foodNode) }; - leavesById = { ...leavesById, ...getLeavesById(foodNode) }; - allLeaves = [...allLeaves, ...getDescendantLeafIds(foodNode)]; - }); - return { - memoizedLeavesById: leavesById, - memoizedAllLeaves: allLeaves, - memoizedNodeText: nodeTexts - }; - }, [data]); - - const moveChecked = (toChosen: boolean) => { - setChosenLeafIds( - prevChosenIds => - toChosen - ? [...prevChosenIds, ...checkedLeafIds] // add checked ids to chosen list - : [...prevChosenIds.filter(x => !checkedLeafIds.includes(x))] // remove checked ids from chosen list - ); - - // uncheck checked ids that just moved - setCheckedLeafIds(prevChecked => - toChosen - ? [...prevChecked.filter(x => chosenLeafIds.includes(x))] - : [...prevChecked.filter(x => !chosenLeafIds.includes(x))] - ); - }; - - const moveAll = (toChosen: boolean) => { - if (toChosen) { - setChosenLeafIds(memoizedAllLeaves); - } else { - setChosenLeafIds([]); - } - }; - - const areAllDescendantsSelected = (node: FoodNode, isChosen: boolean) => - memoizedLeavesById[node.id].every( - id => checkedLeafIds.includes(id) && (isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id)) - ); - const areSomeDescendantsSelected = (node: FoodNode, isChosen: boolean) => - memoizedLeavesById[node.id].some( - id => checkedLeafIds.includes(id) && (isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id)) - ); - - const isNodeChecked = (node: FoodNode, isChosen: boolean) => { - if (areAllDescendantsSelected(node, isChosen)) { - return true; - } - if (areSomeDescendantsSelected(node, isChosen)) { - return null; - } - return false; - }; - - const onOptionCheck = ( - event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, - isChecked: boolean, - node: DualListSelectorTreeItemData, - isChosen: boolean - ) => { - const nodeIdsToCheck = memoizedLeavesById[node.id].filter(id => - isChosen - ? chosenLeafIds.includes(id) && !hiddenChosen.includes(id) - : !chosenLeafIds.includes(id) && !hiddenAvailable.includes(id) - ); - if (isChosen) { - hiddenChosen = []; - } else { - hiddenAvailable = []; - } - setCheckedLeafIds(prevChecked => { - const otherCheckedNodeNames = prevChecked.filter(id => !nodeIdsToCheck.includes(id)); - return !isChecked ? otherCheckedNodeNames : [...otherCheckedNodeNames, ...nodeIdsToCheck]; - }); - }; - - // builds a search input - used in each dual list selector pane - const buildSearchInput = (isChosen: boolean) => { - const onChange = value => (isChosen ? setChosenFilter(value) : setAvailableFilter(value)); - - return ( - onChange('')} /> - ); - }; - - // Builds the DualListSelectorTreeItems from the FoodNodes - const buildOptions = ( - isChosen: boolean, - [node, ...remainingNodes]: FoodNode[], - hasParentMatch: boolean - ): DualListSelectorTreeItemData[] => { - if (!node) { - return []; - } - - const isChecked = isNodeChecked(node, isChosen); - - const filterValue = isChosen ? chosenFilter : availableFilter; - const descendentLeafIds = memoizedLeavesById[node.id]; - const descendentsOnThisPane = isChosen - ? descendentLeafIds.filter(id => chosenLeafIds.includes(id)) - : descendentLeafIds.filter(id => !chosenLeafIds.includes(id)); - - const hasMatchingChildren = - filterValue && descendentsOnThisPane.some(id => memoizedNodeText[id].includes(filterValue)); - const isFilterMatch = filterValue && node.text.includes(filterValue) && descendentsOnThisPane.length > 0; - - // A node is displayed if either of the following is true: - // - There is no filter value and this node or its descendents belong on this pane - // - There is a filter value and this node or one of this node's descendents or ancestors match on this pane - const isDisplayed = - (!filterValue && descendentsOnThisPane.length > 0) || - hasMatchingChildren || - (hasParentMatch && descendentsOnThisPane.length > 0) || - isFilterMatch; - - if (!isDisplayed) { - if (isChosen) { - hiddenChosen.push(node.id); - } else { - hiddenAvailable.push(node.id); - } - } - - return [ - ...(isDisplayed - ? [ - { - id: node.id, - text: node.text, - isChecked, - checkProps: { 'aria-label': `Select ${node.text}` }, - hasBadge: node.children && node.children.length > 0, - badgeProps: { isRead: true }, - defaultExpanded: isChosen ? !!chosenFilter : !!availableFilter, - children: node.children - ? buildOptions(isChosen, node.children, isFilterMatch || hasParentMatch) - : undefined - } - ] - : []), - ...(!isDisplayed && node.children && node.children.length - ? buildOptions(isChosen, node.children, hasParentMatch) - : []), - ...(remainingNodes ? buildOptions(isChosen, remainingNodes, hasParentMatch) : []) - ]; - }; - - const buildPane = (isChosen: boolean): React.ReactNode => { - const options: DualListSelectorTreeItemData[] = buildOptions(isChosen, data, false); - const numOptions = isChosen ? chosenLeafIds.length : memoizedAllLeaves.length - chosenLeafIds.length; - const numSelected = checkedLeafIds.filter(id => - isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id) - ).length; - const status = `${numSelected} of ${numOptions} options selected`; - return ( - - - onOptionCheck(e, isChecked, itemData, isChosen)} - /> - - - ); - }; - - return ( - - {buildPane(false)} - - !chosenLeafIds.includes(x)).length} - onClick={() => moveChecked(true)} - aria-label="Add selected" - > - - - moveAll(true)} - aria-label="Add all" - > - - - moveAll(false)} - aria-label="Remove all" - > - - - moveChecked(false)} - isDisabled={!checkedLeafIds.filter(x => !!chosenLeafIds.includes(x)).length} - aria-label="Remove selected" - > - - - - {buildPane(true)} - - ); -}; - -export const ComposableDualListSelectorTreeExample: React.FunctionComponent = () => ( - -); diff --git a/packages/react-core/src/components/DualListSelector/examples/DualListSelector.md b/packages/react-core/src/components/DualListSelector/examples/DualListSelector.md index 5fd83020a46..1ff7084efec 100644 --- a/packages/react-core/src/components/DualListSelector/examples/DualListSelector.md +++ b/packages/react-core/src/components/DualListSelector/examples/DualListSelector.md @@ -1,828 +1,102 @@ --- id: Dual list selector section: components -cssPrefix: 'pf-c-dual-list-selector' -propComponents: [ - 'DualListSelector', - 'DualListSelectorPane', - 'DualListSelectorControl', - 'DualListSelectorControlsWrapper', - 'DualListSelectorTree', - 'DualListSelectorTreeItemData' -] -beta: true +cssPrefix: 'pf-v6-c-dual-list-selector' +propComponents: + [ + 'DualListSelector', + 'DualListSelectorPane', + 'DualListSelectorList', + 'DualListSelectorListItem', + 'DualListSelectorControlsWrapper', + 'DualListSelectorControl', + 'DualListSelectorTree', + 'DualListSelectorTreeItemData' + ] --- +import { Fragment, useEffect, useMemo, useState } from 'react'; import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; import PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon'; +import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; +import { DragDropSort, DragDropContainer, Droppable as NewDroppable } from '@patternfly/react-drag-drop'; ## Examples +The dual list selector is built in a composable manner to make customization easier. The standard sub-component relationships are arranged as follows: + +```noLive + + + + + + + + + /* A standard Dual list selector has 4 controls */ + + + + + + + + +``` + ### Basic -```js -import React from 'react'; -import { DualListSelector } from '@patternfly/react-core'; - -class BasicDualListSelector extends React.Component { - constructor(props) { - super(props); - this.state = { - availableOptions: ['Option 1', 'Option 2', 'Option 3', 'Option 4'], - chosenOptions: [] - }; - - this.onListChange = (newAvailableOptions, newChosenOptions) => { - this.setState({ - availableOptions: newAvailableOptions.sort(), - chosenOptions: newChosenOptions.sort() - }); - }; - } - - render() { - return ( - - ); - } -} +```ts file="./DualListSelectorBasic.tsx" + ``` ### Basic with tooltips -```js -import React from 'react'; -import { DualListSelector } from '@patternfly/react-core'; - -class BasicDualListSelector extends React.Component { - constructor(props) { - super(props); - this.state = { - availableOptions: ['Option 1', 'Option 2', 'Option 3', 'Option 4'], - chosenOptions: [] - }; - - this.onListChange = (newAvailableOptions, newChosenOptions) => { - this.setState({ - availableOptions: newAvailableOptions.sort(), - chosenOptions: newChosenOptions.sort() - }); - }; - } - - render() { - return ( - - ); - } -} +```ts file="./DualListSelectorBasicTooltips.tsx" + ``` ### Basic with search -```js -import React from 'react'; -import { DualListSelector } from '@patternfly/react-core'; - -class BasicDualListSelectorWithSearch extends React.Component { - constructor(props) { - super(props); - this.state = { - availableOptions: ['Option 1', 'Option 2', 'Option 3', 'Option 4'], - chosenOptions: [] - }; - - this.onListChange = (newAvailableOptions, newChosenOptions) => { - this.setState({ - availableOptions: newAvailableOptions.sort(), - chosenOptions: newChosenOptions.sort() - }); - }; - } - - render() { - return ( - - ); - } -} +```ts file="./DualListSelectorBasicSearch.tsx" + ``` ### Using more complex options with actions -```js -import React from 'react'; -import { Button, ButtonVariant, Checkbox, Dropdown, DropdownItem, DualListSelector, KebabToggle } from '@patternfly/react-core'; -import PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon'; +```ts file="./DualListSelectorComplexOptionsActions.tsx" -class ComplexDualListSelector extends React.Component { - constructor(props) { - super(props); - this.state = { - availableOptions: [Option 1, Option 3, Option 4, Option 2], - chosenOptions: [], - isAvailableKebabOpen: false, - isChosenKebabOpen: false, - isDisabled: false - }; - - this.onSort = panel => { - if (panel === 'available') { - this.setState(prevState => { - const available = prevState.availableOptions.sort((a, b) => { - let returnValue = 0; - if (a.props.children > b.props.children) returnValue = 1; - if (a.props.children < b.props.children) returnValue = -1; - return returnValue; - }); - return { - availableOptions: available - }; - }); - } - - if (panel === 'chosen') { - this.setState(prevState => { - const chosen = prevState.chosenOptions.sort((a, b) => { - let returnValue = 0; - if (a.props.children > b.props.children) returnValue = 1; - if (a.props.children < b.props.children) returnValue = -1; - return returnValue; - }); - return { - chosenOptions: chosen - }; - }); - } - }; - - this.onListChange = (newAvailableOptions, newChosenOptions) => { - this.setState({ - availableOptions: newAvailableOptions, - chosenOptions: newChosenOptions - }); - }; - - this.onToggle = (isOpen, pane) => { - this.setState(prevState => { - return { - isAvailableKebabOpen: pane === 'available' ? isOpen : prevState.isAvailableKebabOpen, - isChosenKebabOpen: pane === 'chosen' ? isOpen : prevState.isChosenKebabOpen - }; - }); - }; - - this.filterOption = (option, input) => { - return option.props.children.includes(input); - }; - } - - render() { - const dropdownItems = [ - Link, - - Action - , - - Second Action - - ]; - - const availableOptionsActions = [ - , - this.onToggle(isOpen, 'available')} id="toggle-id-1" />} - isOpen={this.state.isAvailableKebabOpen} - isPlain - dropdownItems={dropdownItems} - key="availableDropdown" - /> - ]; - - const chosenOptionsActions = [ - , - this.onToggle(isOpen, 'chosen')} id="toggle-id-2" />} - isOpen={this.state.isChosenKebabOpen} - isPlain - dropdownItems={dropdownItems} - key="chosenDropdown" - /> - ]; - - return ( - - - - this.setState({ - isDisabled: !this.state.isDisabled - }) - } - /> - - ); - } -} ``` -### Expandable options - -```js -import React from 'react'; -import { DualListSelector } from '@patternfly/react-core'; - -class TreeDualListSelector extends React.Component { - constructor(props) { - super(props); - this.state = { - chosenOptions: [ - { - id: 'CF1', - text: 'Chosen Folder 1', - isChecked: false, - checkProps: { 'aria-label': 'Chosen Folder 1' }, - hasBadge: true, - badgeProps: { isRead: true }, - children: [ - { id: 'CO1', text: 'Chosen Option 1', isChecked: false, checkProps: { 'aria-label': 'Chosen Option 1' } }, - { - id: 'CF1A', - text: 'Chosen Folder 1A', - isChecked: false, - checkProps: { 'aria-label': 'Chosen Folder 1A' }, - children: [ - { - id: 'CO2', - text: 'Chosen Option 2', - isChecked: false, - checkProps: { 'aria-label': 'Chosen Option 2' } - }, - { - id: 'CO3', - text: 'Chosen Option 3', - isChecked: false, - checkProps: { 'aria-label': 'Chosen Option 3' } - } - ] - }, - { id: 'CO4', text: 'Chosen Option 4', isChecked: false, checkProps: { 'aria-label': 'Chosen Option 4' } } - ] - } - ], - availableOptions: [ - { - id: 'F1', - text: 'Folder 1', - isChecked: false, - checkProps: { 'aria-label': 'Folder 1' }, - hasBadge: true, - badgeProps: { isRead: true }, - children: [ - { id: 'O1', text: 'Option 1', isChecked: false, checkProps: { 'aria-label': 'Option 1' } }, - { - id: 'F1A', - text: 'Folder 1A', - isChecked: false, - checkProps: { 'aria-label': 'Folder 1A' }, - children: [ - { id: 'O2', text: 'Option 2', isChecked: false, checkProps: { 'aria-label': 'Option 2' } }, - { id: 'O3', text: 'Option 3', isChecked: false, checkProps: { 'aria-label': 'Option 3' } } - ] - }, - { id: 'O4', text: 'Option 4', isChecked: false, checkProps: { 'aria-label': 'Option 4' } } - ] - }, - { id: 'O5', text: 'Option 5', isChecked: false, checkProps: { 'aria-label': 'Option 5' } }, - { - id: 'F2', - text: 'Folder 2', - isChecked: false, - checkProps: { 'aria-label': 'Folder 2' }, - children: [ - { id: 'O6', text: 'Option 6', isChecked: false, checkProps: { 'aria-label': 'Option 6' } }, - { id: 'O7', text: 'Option 5', isChecked: false, checkProps: { 'aria-label': 'Option 5 duplicate' } } - ] - } - ] - }; - - this.onListChange = (newAvailableOptions, newChosenOptions) => { - this.setState({ - availableOptions: newAvailableOptions, - chosenOptions: newChosenOptions - }); - }; - } - - render() { - return ( - - ); - } -} +### With tree + +```ts file="DualListSelectorTree.tsx" + ``` -### Composable dual list selector +### Draggable -For more flexibility, a Dual list selector can be built using sub components. When doing so, the intended component -relationships are arranged as follows: +To enable drag and drop, wrap the `` component with ``, define the `variant` property as "DualListSelectorList", and pass both the sortable items and `onDrop` callback to ``. `` will create the component's usual children internally based on the items property, so children inside the `` should not be passed to the wrapped component. -```js noLive -import React from 'react'; -import { DualListSelector, DualListSelectorPane, DualListSelectorList, DualListSelectorListItem, DualListSelectorControlsWrapper, DualListSelectorControl } from '@patternfly/react-core'; +Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page. - +```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DualListSelectorDraggable.tsx" - - - - - - - - {/* The standard Dual list selector has 4 controls */} - - - - - - - - - ``` -Note: Keyboard accessibility and screen reader accessibility for the `DragDrop` component are still in development. - -```js -import React from 'react'; -import { - Button, - ButtonVariant, - DualListSelector, - DualListSelectorPane, - DualListSelectorList, - DualListSelectorListItem, - DualListSelectorControlsWrapper, - DualListSelectorControl, - SearchInput -} from '@patternfly/react-core'; -import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; -import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; -import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; -import PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon'; +### Draggable with multiple drop zones -const ComposableDualListSelector = () => { - const [availableOptions, setAvailableOptions] = React.useState([ - { text: 'Apple', selected: false, isVisible: true }, - { text: 'Banana', selected: false, isVisible: true }, - { text: 'Pineapple', selected: false, isVisible: true }, - { text: 'Orange', selected: false, isVisible: true }, - { text: 'Grape', selected: false, isVisible: true }, - { text: 'Peach', selected: false, isVisible: true }, - { text: 'Strawberry', selected: false, isVisible: true } - ]); - const [chosenOptions, setChosenOptions] = React.useState([]); - const [availableFilter, setAvailableFilter] = React.useState(''); - const [chosenFilter, setChosenFilter] = React.useState(''); - - // callback for moving selected options between lists - const moveSelected = (fromAvailable) => { - const sourceOptions = fromAvailable ? availableOptions : chosenOptions; - const destinationOptions = fromAvailable ? chosenOptions : availableOptions; - for (let i = 0; i < sourceOptions.length; i++) { - const option = sourceOptions[i]; - if (option.selected && option.isVisible) { - sourceOptions.splice(i, 1); - destinationOptions.push(option); - option.selected = false; - i--; - } - } - if (fromAvailable) { - setAvailableOptions([...sourceOptions]); - setChosenOptions([...destinationOptions]); - } else { - setChosenOptions([...sourceOptions]); - setAvailableOptions([...destinationOptions]); - } - }; - - // callback for moving all options between lists - const moveAll = (fromAvailable) => { - if (fromAvailable) { - setChosenOptions([...availableOptions.filter(x => x.isVisible), ...chosenOptions]); - setAvailableOptions([...availableOptions.filter(x => !x.isVisible)]); - } else { - setAvailableOptions([...chosenOptions.filter(x => x.isVisible), ...availableOptions]); - setChosenOptions([...chosenOptions.filter(x => !x.isVisible)]); - } - }; - - // callback when option is selected - const onOptionSelect = (event, index, isChosen) => { - if (isChosen) { - const newChosen = [...chosenOptions]; - newChosen[index].selected = !chosenOptions[index].selected; - setChosenOptions(newChosen); - } else { - const newAvailable = [...availableOptions]; - newAvailable[index].selected = !availableOptions[index].selected; - setAvailableOptions(newAvailable); - } - }; - - // builds a search input - used in each dual list selector pane - const buildSearchInput = (isAvailable) => { - const onChange = (value) => { - isAvailable ? setAvailableFilter(value) : setChosenFilter(value); - const toFilter = isAvailable ? [...availableOptions] : [...chosenOptions]; - toFilter.forEach((option) => { - option.isVisible = value === '' || option.text.toLowerCase().includes(value.toLowerCase()); - }) - }; - - return ( - onChange('')} - /> - ); - }; - - // builds a sort control - passed to both dual list selector panes - const buildSort = (isAvailable) => { - const onSort = () => { - const toSort = isAvailable ? [...availableOptions] : [...chosenOptions]; - toSort.sort((a,b) => { - if (a.text > b.text) return 1; - if (a.text < b.text) return -1; - return 0; - }); - if (isAvailable) { - setAvailableOptions(toSort); - } else { - setChosenOptions(toSort); - } - }; - - return ( - - ); - }; - - return ( - - x.selected && x.isVisible).length} of ${availableOptions.filter(x => x.isVisible).length} options selected`} - searchInput={buildSearchInput(true)} - actions={[buildSort(true)]} - > - - {availableOptions.map((option, index) => { - return option.isVisible ? ( - onOptionSelect(e, index, false)} - > - {option.text} - - ) : null; - })} - - - - option.selected)} - onClick={() => moveSelected(true)} - aria-label="Add selected" - tooltipContent="Add selected" - > - - - moveAll(true)} - aria-label="Add all" - tooltipContent="Add all" - > - - - moveAll(false)} - aria-label="Remove all" - tooltipContent="Remove all" - > - - - moveSelected(false)} - isDisabled={!chosenOptions.some(option => option.selected)} - aria-label="Remove selected" - tooltipContent="Remove selected" - > - - - - x.selected && x.isVisible).length} of ${chosenOptions.filter(x => x.isVisible).length} options selected`} - searchInput={buildSearchInput(false)} - actions={[buildSort(false)]} - isChosen - > - - {chosenOptions.map((option, index) => { - return option.isVisible ? ( - onOptionSelect(e, index, true)} - > - {option.text} - - ) : null; - })} - - - - ); -} -``` +To enable multiple drop zones, wrap the `` component with ``, and create the desired amount of `` components within ``. `` components should be located where `` usually would go for each pane to be made draggable. -### Reordering lists using drag and drop - -To make a pane able to be reordered: - - wrap the `DualListSelectorPane` in a `DragDrop` component - - wrap the `DualListSelectorList` in a `Droppable` component - - wrap the `DualListSelectorListItem` components in a `Draggable` component - - define an `onDrop` callback which reorders the sortable options. - - The `onDrop` function provides the starting location and destination location for a dragged item. It should return - true to enable the 'drop' animation in the new location and false to enable the 'drop' animation back to the item's - old position. - - define an `onDrag` callback which ensures that the drag event will not cross hairs with the `onOptionSelect` click - event set on the option. Note: the `ignoreNextOptionSelect` state value is used to prevent selection while dragging. - -```js -import React from 'react'; -import { - DragDrop, - Droppable, - Draggable, - DualListSelector, - DualListSelectorPane, - DualListSelectorList, - DualListSelectorListItem, - DualListSelectorControlsWrapper, - DualListSelectorControl, -} from '@patternfly/react-core'; -import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; -import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; -import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +Each `` should define the `wrapper` property as the component that acts as the drop zone, ``, and the `items` property of their respective draggable items as an array of `` data. `` should be passed the `onDrop`, `onContainerMove`, and `onCancel` callbacks to handle items being dropped, items moving between droppable containers, and what happens if the drag is cancelled respectively. `` should also be given a `Record` representing all sortable drop zones' items. Both components should define the `variant` property as "DualListSelectorList". -const ComposableDualListSelector = () => { - const [ignoreNextOptionSelect, setIgnoreNextOptionSelect] = React.useState(false); - const [availableOptions, setAvailableOptions] = React.useState([ - { text: 'Apple', selected: false, isVisible: true }, - { text: 'Banana', selected: false, isVisible: true }, - { text: 'Pineapple', selected: false, isVisible: true } - ]); - const [chosenOptions, setChosenOptions] = React.useState([ - { text: 'Orange', selected: false, isVisible: true }, - { text: 'Grape', selected: false, isVisible: true }, - { text: 'Peach', selected: false, isVisible: true }, - { text: 'Strawberry', selected: false, isVisible: true } - ]); - - const moveSelected = (fromAvailable) => { - const sourceOptions = fromAvailable ? availableOptions : chosenOptions; - const destinationOptions = fromAvailable ? chosenOptions : availableOptions; - for (let i = 0; i < sourceOptions.length; i++) { - const option = sourceOptions[i]; - if (option.selected && option.isVisible) { - sourceOptions.splice(i, 1); - destinationOptions.push(option); - option.selected = false; - i--; - } - } - if (fromAvailable) { - setAvailableOptions([...sourceOptions]); - setChosenOptions([...destinationOptions]); - } else { - setChosenOptions([...sourceOptions]); - setAvailableOptions([...destinationOptions]); - } - }; - - const moveAll = (fromAvailable) => { - if (fromAvailable) { - setChosenOptions([...availableOptions.filter(x => x.isVisible), ...chosenOptions]); - setAvailableOptions([...availableOptions.filter(x => !x.isVisible)]); - } else { - setAvailableOptions([...chosenOptions.filter(x => x.isVisible), ...availableOptions]); - setChosenOptions([...chosenOptions.filter(x => !x.isVisible)]); - } - }; - - const onOptionSelect = (event, index, isChosen) => { - if (ignoreNextOptionSelect) { - setIgnoreNextOptionSelect(false); - return; - } - if (isChosen) { - const newChosen = [...chosenOptions]; - newChosen[index].selected = !chosenOptions[index].selected; - setChosenOptions(newChosen); - } else { - const newAvailable = [...availableOptions]; - newAvailable[index].selected = !availableOptions[index].selected; - setAvailableOptions(newAvailable); - } - }; - - const onDrop = (source, dest) => { - if (dest){ - const newList = [...chosenOptions]; - const [removed] = newList.splice(source.index, 1); - newList.splice(dest.index, 0, removed); - setChosenOptions(newList); - return true; - } - return false; - }; - - return ( - - x.selected && x.isVisible).length} of ${availableOptions.filter(x => x.isVisible).length} options selected`} - > - - {availableOptions.map((option, index) => { - return option.isVisible ? ( - onOptionSelect(e, index, false)} - > - {option.text} - - ) : null; - })} - - - - option.selected)} - onClick={() => moveSelected(true)} - aria-label="Add selected" - > - - - moveAll(true)} - aria-label="Add all" - > - - - moveAll(false)} - aria-label="Remove all" - > - - - moveSelected(false)} - isDisabled={!chosenOptions.some(option => option.selected)} - aria-label="Remove selected" - > - - - - { setIgnoreNextOptionSelect(true); return true; }} onDrop={onDrop}> - x.selected && x.isVisible).length} of ${chosenOptions.filter(x => x.isVisible).length} options selected`} - isChosen - > - - - {chosenOptions.map((option, index) => { - return option.isVisible ? ( - - onOptionSelect(e, index, true)} - isDraggable - > - {option.text} - - - ) : null; - })} - - - - - - ); -} -``` +Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page. -### Composable dual list selector tree -```ts file="ComposableTree.tsx" -``` +```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DragDropContainerDualListSelector.tsx" +``` diff --git a/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasic.tsx b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasic.tsx new file mode 100644 index 00000000000..b1e77ed2a6a --- /dev/null +++ b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasic.tsx @@ -0,0 +1,153 @@ +import { useState } from 'react'; +import { + DualListSelector, + DualListSelectorPane, + DualListSelectorList, + DualListSelectorListItem, + DualListSelectorControlsWrapper, + DualListSelectorControl +} from '@patternfly/react-core'; +import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; +import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; +import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; +import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; + +interface Option { + text: string; + selected: boolean; + isVisible: boolean; +} + +export const DualListSelectorBasic: React.FunctionComponent = () => { + const [availableOptions, setAvailableOptions] = useState([ + { text: 'Option 1', selected: false, isVisible: true }, + { text: 'Option 2', selected: false, isVisible: true }, + { text: 'Option 3', selected: false, isVisible: true }, + { text: 'Option 4', selected: false, isVisible: true } + ]); + const [chosenOptions, setChosenOptions] = useState([]); + + // callback for moving selected options between lists + const moveSelected = (fromAvailable: boolean) => { + const sourceOptions = fromAvailable ? availableOptions : chosenOptions; + const destinationOptions = fromAvailable ? chosenOptions : availableOptions; + for (let i = 0; i < sourceOptions.length; i++) { + const option = sourceOptions[i]; + if (option.selected && option.isVisible) { + sourceOptions.splice(i, 1); + destinationOptions.push(option); + option.selected = false; + i--; + } + } + if (fromAvailable) { + setAvailableOptions([...sourceOptions]); + setChosenOptions([...destinationOptions]); + } else { + setChosenOptions([...sourceOptions]); + setAvailableOptions([...destinationOptions]); + } + }; + + // callback for moving all options between lists + const moveAll = (fromAvailable: boolean) => { + if (fromAvailable) { + setChosenOptions([...availableOptions.filter((option) => option.isVisible), ...chosenOptions]); + setAvailableOptions([...availableOptions.filter((option) => !option.isVisible)]); + } else { + setAvailableOptions([...chosenOptions.filter((option) => option.isVisible), ...availableOptions]); + setChosenOptions([...chosenOptions.filter((option) => !option.isVisible)]); + } + }; + + // callback when option is selected + const onOptionSelect = ( + event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, + index: number, + isChosen: boolean + ) => { + if (isChosen) { + const newChosen = [...chosenOptions]; + newChosen[index].selected = !chosenOptions[index].selected; + setChosenOptions(newChosen); + } else { + const newAvailable = [...availableOptions]; + newAvailable[index].selected = !availableOptions[index].selected; + setAvailableOptions(newAvailable); + } + }; + + return ( + + option.selected && option.isVisible).length} of ${ + availableOptions.filter((option) => option.isVisible).length + } options selected`} + > + + {availableOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, false)} + > + {option.text} + + ) : null + )} + + + + option.selected)} + onClick={() => moveSelected(true)} + aria-label="Add selected" + icon={} + /> + moveAll(true)} + aria-label="Add all" + icon={} + /> + moveAll(false)} + aria-label="Remove all" + icon={} + /> + moveSelected(false)} + isDisabled={!chosenOptions.some((option) => option.selected)} + aria-label="Remove selected" + icon={} + /> + + option.selected && option.isVisible).length} of ${ + chosenOptions.filter((option) => option.isVisible).length + } options selected`} + isChosen + > + + {chosenOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, true)} + > + {option.text} + + ) : null + )} + + + + ); +}; diff --git a/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasicSearch.tsx b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasicSearch.tsx new file mode 100644 index 00000000000..cf5365c8efc --- /dev/null +++ b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasicSearch.tsx @@ -0,0 +1,208 @@ +import { useState } from 'react'; +import { + Button, + DualListSelector, + DualListSelectorPane, + DualListSelectorList, + DualListSelectorListItem, + DualListSelectorControlsWrapper, + DualListSelectorControl, + SearchInput, + EmptyState, + EmptyStateVariant, + EmptyStateFooter, + EmptyStateBody, + EmptyStateActions +} from '@patternfly/react-core'; +import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; +import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; +import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; +import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; + +interface Option { + text: string; + selected: boolean; + isVisible: boolean; +} + +export const DualListSelectorSearch: React.FunctionComponent = () => { + const [availableOptions, setAvailableOptions] = useState([ + { text: 'Option 1', selected: false, isVisible: true }, + { text: 'Option 2', selected: false, isVisible: true }, + { text: 'Option 3', selected: false, isVisible: true }, + { text: 'Option 4', selected: false, isVisible: true } + ]); + + const [chosenOptions, setChosenOptions] = useState([]); + const [availableFilter, setAvailableFilter] = useState(''); + const [chosenFilter, setChosenFilter] = useState(''); + + // callback for moving selected options between lists + const moveSelected = (fromAvailable: boolean) => { + const sourceOptions = fromAvailable ? availableOptions : chosenOptions; + const destinationOptions = fromAvailable ? chosenOptions : availableOptions; + for (let i = 0; i < sourceOptions.length; i++) { + const option = sourceOptions[i]; + if (option.selected && option.isVisible) { + sourceOptions.splice(i, 1); + destinationOptions.push(option); + option.selected = false; + i--; + } + } + if (fromAvailable) { + setAvailableOptions([...sourceOptions]); + setChosenOptions([...destinationOptions]); + } else { + setChosenOptions([...sourceOptions]); + setAvailableOptions([...destinationOptions]); + } + }; + + // callback for moving all options between lists + const moveAll = (fromAvailable: boolean) => { + if (fromAvailable) { + setChosenOptions([...availableOptions.filter((option) => option.isVisible), ...chosenOptions]); + setAvailableOptions([...availableOptions.filter((option) => !option.isVisible)]); + } else { + setAvailableOptions([...chosenOptions.filter((option) => option.isVisible), ...availableOptions]); + setChosenOptions([...chosenOptions.filter((option) => !option.isVisible)]); + } + }; + + // callback when option is selected + const onOptionSelect = ( + event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, + index: number, + isChosen: boolean + ) => { + if (isChosen) { + const newChosen = [...chosenOptions]; + newChosen[index].selected = !chosenOptions[index].selected; + setChosenOptions(newChosen); + } else { + const newAvailable = [...availableOptions]; + newAvailable[index].selected = !availableOptions[index].selected; + setAvailableOptions(newAvailable); + } + }; + + const onFilterChange = (value: string, isAvailable: boolean) => { + isAvailable ? setAvailableFilter(value) : setChosenFilter(value); + const toFilter = isAvailable ? [...availableOptions] : [...chosenOptions]; + toFilter.forEach((option) => { + option.isVisible = value === '' || option.text.toLowerCase().includes(value.toLowerCase()); + }); + }; + + // builds a search input - used in each dual list selector pane + const buildSearchInput = (isAvailable: boolean) => ( + onFilterChange(value, isAvailable)} + onClear={() => onFilterChange('', isAvailable)} + aria-label={isAvailable ? 'Search available options' : 'Search chosen options'} + /> + ); + + const buildEmptyState = (isAvailable: boolean) => ( + + No results match the filter criteria. Clear all filters and try again. + + + + + + + ); + + return ( + + option.selected && option.isVisible).length} of ${ + availableOptions.filter((option) => option.isVisible).length + } options selected`} + searchInput={buildSearchInput(true)} + listMinHeight="300px" + > + {availableFilter !== '' && + availableOptions.filter((option) => option.isVisible).length === 0 && + buildEmptyState(true)} + + + {availableOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, false)} + > + {option.text} + + ) : null + )} + + + + option.selected)} + onClick={() => moveSelected(true)} + aria-label="Add selected" + icon={} + /> + moveAll(true)} + aria-label="Add all" + icon={} + /> + moveAll(false)} + aria-label="Remove all" + icon={} + /> + moveSelected(false)} + isDisabled={!chosenOptions.some((option) => option.selected)} + aria-label="Remove selected" + icon={} + /> + + option.selected && option.isVisible).length} of ${ + chosenOptions.filter((option) => option.isVisible).length + } options selected`} + searchInput={buildSearchInput(false)} + listMinHeight="300px" + isChosen + > + {chosenFilter !== '' && + chosenOptions.filter((option) => option.isVisible).length === 0 && + buildEmptyState(false)} + {chosenOptions.filter((option) => option.isVisible).length > 0 && ( + + {chosenOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, true)} + > + {option.text} + + ) : null + )} + + )} + + + ); +}; diff --git a/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasicTooltips.tsx b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasicTooltips.tsx new file mode 100644 index 00000000000..96ed69cd375 --- /dev/null +++ b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorBasicTooltips.tsx @@ -0,0 +1,161 @@ +import { useState } from 'react'; +import { + DualListSelector, + DualListSelectorPane, + DualListSelectorList, + DualListSelectorListItem, + DualListSelectorControlsWrapper, + DualListSelectorControl +} from '@patternfly/react-core'; +import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; +import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; +import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; +import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; + +interface Option { + text: string; + selected: boolean; + isVisible: boolean; +} + +export const DualListSelectorBasic: React.FunctionComponent = () => { + const [availableOptions, setAvailableOptions] = useState([ + { text: 'Option 1', selected: false, isVisible: true }, + { text: 'Option 2', selected: false, isVisible: true }, + { text: 'Option 3', selected: false, isVisible: true }, + { text: 'Option 4', selected: false, isVisible: true } + ]); + const [chosenOptions, setChosenOptions] = useState([]); + + // callback for moving selected options between lists + const moveSelected = (fromAvailable: boolean) => { + const sourceOptions = fromAvailable ? availableOptions : chosenOptions; + const destinationOptions = fromAvailable ? chosenOptions : availableOptions; + for (let i = 0; i < sourceOptions.length; i++) { + const option = sourceOptions[i]; + if (option.selected && option.isVisible) { + sourceOptions.splice(i, 1); + destinationOptions.push(option); + option.selected = false; + i--; + } + } + if (fromAvailable) { + setAvailableOptions([...sourceOptions]); + setChosenOptions([...destinationOptions]); + } else { + setChosenOptions([...sourceOptions]); + setAvailableOptions([...destinationOptions]); + } + }; + + // callback for moving all options between lists + const moveAll = (fromAvailable: boolean) => { + if (fromAvailable) { + setChosenOptions([...availableOptions.filter((option) => option.isVisible), ...chosenOptions]); + setAvailableOptions([...availableOptions.filter((option) => !option.isVisible)]); + } else { + setAvailableOptions([...chosenOptions.filter((option) => option.isVisible), ...availableOptions]); + setChosenOptions([...chosenOptions.filter((option) => !option.isVisible)]); + } + }; + + // callback when option is selected + const onOptionSelect = ( + event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, + index: number, + isChosen: boolean + ) => { + if (isChosen) { + const newChosen = [...chosenOptions]; + newChosen[index].selected = !chosenOptions[index].selected; + setChosenOptions(newChosen); + } else { + const newAvailable = [...availableOptions]; + newAvailable[index].selected = !availableOptions[index].selected; + setAvailableOptions(newAvailable); + } + }; + + return ( + + option.selected && option.isVisible).length} of ${ + availableOptions.filter((option) => option.isVisible).length + } options selected`} + > + + {availableOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, false)} + > + {option.text} + + ) : null + )} + + + + option.selected)} + onClick={() => moveSelected(true)} + aria-label="Add selected" + tooltipContent="Add selected" + tooltipProps={{ position: 'top', 'aria-live': 'off' }} + icon={} + /> + moveAll(true)} + aria-label="Add all" + tooltipContent="Add all" + tooltipProps={{ position: 'right', 'aria-live': 'off' }} + icon={} + /> + moveAll(false)} + aria-label="Remove all" + tooltipContent="Remove all" + tooltipProps={{ position: 'left', 'aria-live': 'off' }} + icon={} + /> + moveSelected(false)} + isDisabled={!chosenOptions.some((option) => option.selected)} + aria-label="Remove selected" + tooltipContent="Remove selected" + tooltipProps={{ position: 'bottom', 'aria-live': 'off' }} + icon={} + /> + + option.selected && option.isVisible).length} of ${ + chosenOptions.filter((option) => option.isVisible).length + } options selected`} + isChosen + > + + {chosenOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, true)} + > + {option.text} + + ) : null + )} + + + + ); +}; diff --git a/packages/react-core/src/components/DualListSelector/examples/DualListSelectorComplexOptionsActions.tsx b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorComplexOptionsActions.tsx new file mode 100644 index 00000000000..5830aee7237 --- /dev/null +++ b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorComplexOptionsActions.tsx @@ -0,0 +1,337 @@ +import { Fragment, useState } from 'react'; +import { + Button, + ButtonVariant, + Checkbox, + Dropdown, + DropdownList, + DropdownItem, + DualListSelector, + DualListSelectorPane, + DualListSelectorList, + DualListSelectorListItem, + DualListSelectorControlsWrapper, + DualListSelectorControl, + SearchInput, + EmptyState, + EmptyStateVariant, + EmptyStateFooter, + EmptyStateBody, + EmptyStateActions, + MenuToggle, + MenuToggleElement +} from '@patternfly/react-core'; +import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; +import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; +import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; +import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon'; +import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +interface Option { + text: string; + selected: boolean; + isVisible: boolean; +} + +export const DualListSelectorComplexOptionsActionsNext: React.FunctionComponent = () => { + const [availableOptions, setAvailableOptions] = useState([ + { text: 'Option 1', selected: false, isVisible: true }, + { text: 'Option 2', selected: false, isVisible: true }, + { text: 'Option 3', selected: false, isVisible: true }, + { text: 'Option 4', selected: false, isVisible: true } + ]); + + const [chosenOptions, setChosenOptions] = useState([]); + const [isAvailableKebabOpen, setIsAvailableKebabOpen] = useState(false); + const [isChosenKebabOpen, setIsChosenKebabOpen] = useState(false); + const [availableFilter, setAvailableFilter] = useState(''); + const [chosenFilter, setChosenFilter] = useState(''); + const [isDisabled, setIsDisabled] = useState(false); + + // callback for moving selected options between lists + const moveSelected = (fromAvailable: boolean) => { + const sourceOptions = fromAvailable ? availableOptions : chosenOptions; + const destinationOptions = fromAvailable ? chosenOptions : availableOptions; + for (let i = 0; i < sourceOptions.length; i++) { + const option = sourceOptions[i]; + if (option.selected && option.isVisible) { + sourceOptions.splice(i, 1); + destinationOptions.push(option); + option.selected = false; + i--; + } + } + if (fromAvailable) { + setAvailableOptions([...sourceOptions]); + setChosenOptions([...destinationOptions]); + } else { + setChosenOptions([...sourceOptions]); + setAvailableOptions([...destinationOptions]); + } + }; + + // callback for moving all options between lists + const moveAll = (fromAvailable: boolean) => { + if (fromAvailable) { + setChosenOptions([...availableOptions.filter((option) => option.isVisible), ...chosenOptions]); + setAvailableOptions([...availableOptions.filter((option) => !option.isVisible)]); + } else { + setAvailableOptions([...chosenOptions.filter((option) => option.isVisible), ...availableOptions]); + setChosenOptions([...chosenOptions.filter((option) => !option.isVisible)]); + } + }; + + // callback when option is selected + const onOptionSelect = ( + event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, + index: number, + isChosen: boolean + ) => { + if (isChosen) { + const newChosen = [...chosenOptions]; + newChosen[index].selected = !chosenOptions[index].selected; + setChosenOptions(newChosen); + } else { + const newAvailable = [...availableOptions]; + newAvailable[index].selected = !availableOptions[index].selected; + setAvailableOptions(newAvailable); + } + }; + + const onFilterChange = (value: string, isAvailable: boolean) => { + isAvailable ? setAvailableFilter(value) : setChosenFilter(value); + const toFilter = isAvailable ? [...availableOptions] : [...chosenOptions]; + toFilter.forEach((option) => { + option.isVisible = value === '' || option.text.toLowerCase().includes(value.toLowerCase()); + }); + }; + + // builds a search input - used in each dual list selector pane + const buildSearchInput = (isAvailable: boolean) => ( + onFilterChange(value, isAvailable)} + onClear={() => onFilterChange('', isAvailable)} + isDisabled={isDisabled} + aria-label={isAvailable ? 'Search available options' : 'Search chosen options'} + /> + ); + + // builds a sort control - passed to both dual list selector panes + const buildSort = (isAvailable: boolean) => { + const onSort = () => { + const toSort = isAvailable ? [...availableOptions] : [...chosenOptions]; + toSort.sort((a, b) => { + if (a.text > b.text) { + return 1; + } + if (a.text < b.text) { + return -1; + } + return 0; + }); + if (isAvailable) { + setAvailableOptions(toSort); + } else { + setChosenOptions(toSort); + } + }; + + const onToggle = (pane: string) => { + if (pane === 'available') { + setIsAvailableKebabOpen(!isAvailableKebabOpen); + } else { + setIsChosenKebabOpen(!isChosenKebabOpen); + } + }; + + return isAvailable + ? [ + + + + + ); + + return ( + + + option.selected && option.isVisible).length} of ${ + availableOptions.filter((option) => option.isVisible).length + } options selected`} + searchInput={buildSearchInput(true)} + actions={[buildSort(true)]} + listMinHeight="300px" + isDisabled={isDisabled} + > + {availableFilter !== '' && + availableOptions.filter((option) => option.isVisible).length === 0 && + buildEmptyState(true)} + + + {availableOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, false)} + isDisabled={isDisabled} + > + {option.text} + + ) : null + )} + + + + option.selected) || isDisabled} + onClick={() => moveSelected(true)} + aria-label="Add selected" + icon={} + /> + moveAll(true)} + aria-label="Add all" + icon={} + /> + moveAll(false)} + aria-label="Remove all" + icon={} + /> + moveSelected(false)} + isDisabled={!chosenOptions.some((option) => option.selected) || isDisabled} + aria-label="Remove selected" + icon={} + /> + + option.selected && option.isVisible).length} of ${ + chosenOptions.filter((option) => option.isVisible).length + } options selected`} + searchInput={buildSearchInput(false)} + actions={[buildSort(false)]} + listMinHeight="300px" + isChosen + > + {chosenFilter !== '' && + chosenOptions.filter((option) => option.isVisible).length === 0 && + buildEmptyState(false)} + {chosenOptions.filter((option) => option.isVisible).length > 0 && ( + + {chosenOptions.map((option, index) => + option.isVisible ? ( + onOptionSelect(e, index, true)} + isDisabled={isDisabled} + > + {option.text} + + ) : null + )} + + )} + + + setIsDisabled(!isDisabled)} + /> + + ); +}; diff --git a/packages/react-core/src/components/DualListSelector/examples/DualListSelectorTree.tsx b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorTree.tsx new file mode 100644 index 00000000000..a893541ed5e --- /dev/null +++ b/packages/react-core/src/components/DualListSelector/examples/DualListSelectorTree.tsx @@ -0,0 +1,371 @@ +import { useMemo, useState } from 'react'; +import { + DualListSelector, + DualListSelectorPane, + DualListSelectorList, + DualListSelectorControlsWrapper, + DualListSelectorControl, + DualListSelectorTree, + DualListSelectorTreeItemData, + SearchInput, + Button, + EmptyState, + EmptyStateVariant, + EmptyStateFooter, + EmptyStateBody, + EmptyStateActions +} from '@patternfly/react-core'; +import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon'; +import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon'; +import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; +import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; + +interface FoodNode { + id: string; + text: string; + children?: FoodNode[]; +} + +interface ExampleProps { + data: FoodNode[]; +} + +export const DualListSelectorComposableTree: React.FunctionComponent = ({ data }: ExampleProps) => { + const [checkedLeafIds, setCheckedLeafIds] = useState([]); + const [chosenLeafIds, setChosenLeafIds] = useState(['beans', 'beef', 'chicken', 'tofu']); + const [chosenFilter, setChosenFilter] = useState(''); + const [availableFilter, setAvailableFilter] = useState(''); + + // helper function to build memoized lists + const buildTextById = (node: FoodNode): { [key: string]: string } => { + let textById = {}; + if (!node) { + return textById; + } + textById[node.id] = node.text; + if (node.children) { + node.children.forEach((child) => { + textById = { ...textById, ...buildTextById(child) }; + }); + } + return textById; + }; + + // helper function to build memoized lists + const getDescendantLeafIds = (node: FoodNode): string[] => { + if (!node.children || !node.children.length) { + return [node.id]; + } else { + let childrenIds: string[] = []; + node.children.forEach((child) => { + childrenIds = [...childrenIds, ...getDescendantLeafIds(child)]; + }); + return childrenIds; + } + }; + + // helper function to build memoized lists + const getLeavesById = (node: FoodNode): { [key: string]: string[] } => { + let leavesById = {}; + if (!node.children || !node.children.length) { + leavesById[node.id] = [node.id]; + } else { + node.children.forEach((child) => { + leavesById[node.id] = getDescendantLeafIds(node); + leavesById = { ...leavesById, ...getLeavesById(child) }; + }); + } + return leavesById; + }; + + // Builds a map of child leaf nodes by node id - memoized so that it only rebuilds the list if the data changes. + const { memoizedLeavesById, memoizedAllLeaves, memoizedNodeTexts } = useMemo(() => { + let leavesById = {}; + let allLeaves: string[] = []; + let nodeTexts = {}; + data.forEach((foodNode) => { + nodeTexts = { ...nodeTexts, ...buildTextById(foodNode) }; + leavesById = { ...leavesById, ...getLeavesById(foodNode) }; + allLeaves = [...allLeaves, ...getDescendantLeafIds(foodNode)]; + }); + return { + memoizedLeavesById: leavesById, + memoizedAllLeaves: allLeaves, + memoizedNodeTexts: nodeTexts + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [data]); + + const matchesFilter = (value: string, filter: string) => value.toLowerCase().includes(filter.trim().toLowerCase()); + + const getVisibleLeafIds = (leafIds: string[], filter: string) => { + const filterMatchingNodeIds = Object.keys(memoizedLeavesById).filter((nodeId) => + matchesFilter(memoizedNodeTexts[nodeId], filter) + ); + const filterMatchingLeafIds = filterMatchingNodeIds.map((nodeId) => memoizedLeavesById[nodeId]).flat(); + return leafIds.filter((leafId) => filterMatchingLeafIds.includes(leafId)); + }; + + const availableLeafIds = memoizedAllLeaves.filter((leafId) => !chosenLeafIds.includes(leafId)); + const visibleChosenLeafIds = getVisibleLeafIds(chosenLeafIds, chosenFilter); + const visibleAvailableLeafIds = getVisibleLeafIds(availableLeafIds, availableFilter); + + const moveChecked = (toChosen: boolean) => { + const visibleCheckedChosenLeafIds = checkedLeafIds.filter((leafId) => visibleChosenLeafIds.includes(leafId)); + const visibleCheckedAvailableLeafIds = checkedLeafIds.filter((leafId) => visibleAvailableLeafIds.includes(leafId)); + + setChosenLeafIds( + (prevChosenIds) => + toChosen + ? [...prevChosenIds, ...visibleCheckedAvailableLeafIds] // add visible checked ids to chosen list + : prevChosenIds.filter((x) => !visibleCheckedChosenLeafIds.includes(x)) // remove visible checked ids from chosen list + ); + + // uncheck checked ids that just moved + setCheckedLeafIds((prevChecked) => + toChosen + ? prevChecked.filter((x) => !visibleCheckedAvailableLeafIds.includes(x)) + : prevChecked.filter((x) => !visibleCheckedChosenLeafIds.includes(x)) + ); + }; + + const moveAll = (toChosen: boolean) => { + if (toChosen) { + setChosenLeafIds((prevChosenIds) => [...prevChosenIds, ...visibleAvailableLeafIds]); + } else { + setChosenLeafIds((prevChosenIds) => prevChosenIds.filter((id) => !visibleChosenLeafIds.includes(id))); + } + }; + + const areAllDescendantsSelected = (node: FoodNode, isChosen: boolean) => + memoizedLeavesById[node.id].every( + (id) => checkedLeafIds.includes(id) && (isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id)) + ); + const areSomeDescendantsSelected = (node: FoodNode, isChosen: boolean) => + memoizedLeavesById[node.id].some( + (id) => checkedLeafIds.includes(id) && (isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id)) + ); + + const isNodeChecked = (node: FoodNode, isChosen: boolean) => { + if (areAllDescendantsSelected(node, isChosen)) { + return true; + } + if (areSomeDescendantsSelected(node, isChosen)) { + return false; + } + return false; + }; + + const onOptionCheck = ( + event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, + isChecked: boolean, + node: DualListSelectorTreeItemData, + isChosen: boolean + ) => { + const nodeIdsToCheck = memoizedLeavesById[node.id].filter((id) => + isChosen ? visibleChosenLeafIds.includes(id) : visibleAvailableLeafIds.includes(id) + ); + + setCheckedLeafIds((prevChecked) => { + const otherCheckedNodeNames = prevChecked.filter((id) => !nodeIdsToCheck.includes(id)); + return !isChecked ? otherCheckedNodeNames : [...otherCheckedNodeNames, ...nodeIdsToCheck]; + }); + }; + + // builds a search input - used in each dual list selector pane + const buildSearchInput = (isChosen: boolean) => { + const onChange = (value) => (isChosen ? setChosenFilter(value) : setAvailableFilter(value)); + + return ( + onChange(value)} + onClear={() => onChange('')} + aria-label={isChosen ? 'Search chosen items' : 'Search available items'} + /> + ); + }; + + // Builds the DualListSelectorTreeItems from the FoodNodes + const buildOptions = ( + isChosen: boolean, + [node, ...remainingNodes]: FoodNode[], + hasParentMatch: boolean + ): DualListSelectorTreeItemData[] => { + if (!node) { + return []; + } + + const isChecked = isNodeChecked(node, isChosen); + + const filterValue = isChosen ? chosenFilter : availableFilter; + const descendentLeafIds = memoizedLeavesById[node.id]; + const descendentsOnThisPane = isChosen + ? descendentLeafIds.filter((id) => chosenLeafIds.includes(id)) + : descendentLeafIds.filter((id) => !chosenLeafIds.includes(id)); + + const hasMatchingChildren = + filterValue && descendentsOnThisPane.some((id) => matchesFilter(memoizedNodeTexts[id], filterValue)); + const isFilterMatch = filterValue && matchesFilter(node.text, filterValue) && descendentsOnThisPane.length > 0; + + // A node is displayed if either of the following is true: + // - There is no filter value and this node or its descendents belong on this pane + // - There is a filter value and this node or one of this node's descendents or ancestors match on this pane + const isDisplayed = + (!filterValue && descendentsOnThisPane.length > 0) || + hasMatchingChildren || + (hasParentMatch && descendentsOnThisPane.length > 0) || + isFilterMatch; + + return [ + ...(isDisplayed + ? [ + { + id: node.id, + text: node.text, + isChecked, + checkProps: { 'aria-label': `Select ${node.text}` }, + hasBadge: node.children && node.children.length > 0, + badgeProps: { isRead: true }, + defaultExpanded: isChosen ? !!chosenFilter : !!availableFilter, + children: node.children + ? buildOptions(isChosen, node.children, isFilterMatch || hasParentMatch) + : undefined + } + ] + : []), + ...(!isDisplayed && node.children && node.children.length + ? buildOptions(isChosen, node.children, hasParentMatch) + : []), + ...(remainingNodes ? buildOptions(isChosen, remainingNodes, hasParentMatch) : []) + ]; + }; + + const buildPane = (isChosen: boolean): React.ReactNode => { + const options: DualListSelectorTreeItemData[] = buildOptions(isChosen, data, false); + const numOptions = isChosen ? visibleChosenLeafIds.length : visibleAvailableLeafIds.length; + const numSelected = checkedLeafIds.filter((id) => + isChosen ? visibleChosenLeafIds.includes(id) : visibleAvailableLeafIds.includes(id) + ).length; + const status = `${numSelected} of ${numOptions} options selected`; + const filterApplied = isChosen ? chosenFilter !== '' : availableFilter !== ''; + return ( + + {filterApplied && options.length === 0 && ( + + No results match the filter criteria. Clear all filters and try again. + + + + + + + )} + {options.length > 0 && ( + + onOptionCheck(e, isChecked, itemData, isChosen)} + /> + + )} + + ); + }; + + return ( + + {buildPane(false)} + + visibleAvailableLeafIds.includes(x)).length} + onClick={() => moveChecked(true)} + aria-label="Add selected" + icon={} + /> + moveAll(true)} + aria-label="Add all" + icon={} + /> + moveAll(false)} + aria-label="Remove all" + icon={} + /> + moveChecked(false)} + isDisabled={!checkedLeafIds.filter((x) => visibleChosenLeafIds.includes(x)).length} + aria-label="Remove selected" + icon={} + /> + + {buildPane(true)} + + ); +}; + +export const DualListSelectorComposableTreeExample: React.FunctionComponent = () => ( + +); diff --git a/packages/react-core/src/components/DualListSelector/treeUtils.ts b/packages/react-core/src/components/DualListSelector/treeUtils.ts index 9d32965191a..596dbbadffd 100644 --- a/packages/react-core/src/components/DualListSelector/treeUtils.ts +++ b/packages/react-core/src/components/DualListSelector/treeUtils.ts @@ -2,7 +2,7 @@ import { DualListSelectorTreeItemData } from './DualListSelectorTree'; export function flattenTree(tree: DualListSelectorTreeItemData[]): string[] { let result = [] as string[]; - tree.forEach(item => { + tree.forEach((item) => { if (item.children) { result = result.concat(flattenTree(item.children)); } else { @@ -14,7 +14,7 @@ export function flattenTree(tree: DualListSelectorTreeItemData[]): string[] { export function flattenTreeWithFolders(tree: DualListSelectorTreeItemData[]): string[] { let result = [] as string[]; - tree.forEach(item => { + tree.forEach((item) => { result.push(item.id); if (item.children) { result = result.concat(flattenTreeWithFolders(item.children)); @@ -25,7 +25,7 @@ export function flattenTreeWithFolders(tree: DualListSelectorTreeItemData[]): st export function filterFolders(tree: DualListSelectorTreeItemData[], inputList: string[]): string[] { let result = [] as string[]; - tree.forEach(item => { + tree.forEach((item) => { if (item.children) { result = result.concat(filterFolders(item.children, inputList)); } else { @@ -44,8 +44,8 @@ export function filterTreeItems(item: DualListSelectorTreeItemData, inputList: s if (item.children) { return ( (item.children = item.children - .map(opt => Object.assign({}, opt)) - .filter(child => filterTreeItems(child, inputList))).length > 0 + .map((opt) => Object.assign({}, opt)) + .filter((child) => filterTreeItems(child, inputList))).length > 0 ); } } @@ -54,8 +54,8 @@ export function filterTreeItemsWithoutFolders(item: DualListSelectorTreeItemData if (item.children) { return ( (item.children = item.children - .map(opt => Object.assign({}, opt)) - .filter(child => + .map((opt) => Object.assign({}, opt)) + .filter((child) => child.children ? filterTreeItemsWithoutFolders(child, inputList) : filterTreeItems(child, inputList) )).length > 0 ); @@ -70,8 +70,8 @@ export function filterRestTreeItems(item: DualListSelectorTreeItemData, inputLis if (item.children) { const child = (item.children = item.children - .map(opt => Object.assign({}, opt)) - .filter(child => filterRestTreeItems(child, inputList))).length > 0; + .map((opt) => Object.assign({}, opt)) + .filter((child) => filterRestTreeItems(child, inputList))).length > 0; return child; } diff --git a/packages/react-core/src/components/EmptyState/EmptyState.tsx b/packages/react-core/src/components/EmptyState/EmptyState.tsx index f70dbb35a92..f39ca81e911 100644 --- a/packages/react-core/src/components/EmptyState/EmptyState.tsx +++ b/packages/react-core/src/components/EmptyState/EmptyState.tsx @@ -1,46 +1,85 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; +import { EmptyStateHeader } from './EmptyStateHeader'; +import { statusIcons } from '../../helpers'; export enum EmptyStateVariant { 'xs' = 'xs', - small = 'small', - large = 'large', + sm = 'sm', + lg = 'lg', 'xl' = 'xl', full = 'full' } +export enum EmptyStateStatus { + danger = 'danger', + warning = 'warning', + success = 'success', + info = 'info', + custom = 'custom' +} + export interface EmptyStateProps extends React.HTMLProps { - /** Additional classes added to the EmptyState */ + /** Additional classes added to the empty state */ className?: string; - /** Content rendered inside the EmptyState */ - children: React.ReactNode; - /** Modifies EmptyState max-width */ - variant?: 'xs' | 'small' | 'large' | 'xl' | 'full'; + /** Content rendered inside the empty state */ + children?: React.ReactNode; + /** Modifies empty state max-width and sizes of icon, title and body */ + variant?: 'xs' | 'sm' | 'lg' | 'xl' | 'full'; /** Cause component to consume the available height of its container */ isFullHeight?: boolean; + /** Status of the empty state, will set a default status icon and color. Icon can be overwritten using the icon prop */ + status?: 'danger' | 'warning' | 'success' | 'info' | 'custom'; + /** Additional class names to apply to the empty state header */ + headerClassName?: string; + /** Additional classes added to the title inside empty state header */ + titleClassName?: string; + /** Text of the title inside empty state header, will be wrapped in headingLevel */ + titleText?: React.ReactNode; + /** Empty state icon element to be rendered. Can also be a spinner component */ + icon?: React.ComponentType; + /** The heading level to use, default is h1 */ + headingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } export const EmptyState: React.FunctionComponent = ({ children, - className = '', + className, variant = EmptyStateVariant.full, isFullHeight, + status, + icon: customIcon, + titleText, + titleClassName, + headerClassName, + headingLevel, ...props -}: EmptyStateProps) => ( -
    -
    {children}
    -
    -); +}: EmptyStateProps) => { + const statusIcon = status && statusIcons[status]; + const icon = customIcon || statusIcon; + + return ( +
    +
    + + {children} +
    +
    + ); +}; EmptyState.displayName = 'EmptyState'; diff --git a/packages/react-core/src/components/EmptyState/EmptyStateActions.tsx b/packages/react-core/src/components/EmptyState/EmptyStateActions.tsx new file mode 100644 index 00000000000..e6a10d7cf9d --- /dev/null +++ b/packages/react-core/src/components/EmptyState/EmptyStateActions.tsx @@ -0,0 +1,20 @@ +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; + +export interface EmptyStateActionsProps extends React.HTMLProps { + /** Content rendered inside the empty state actions */ + children?: React.ReactNode; + /** Additional classes added to the empty state actions */ + className?: string; +} + +export const EmptyStateActions: React.FunctionComponent = ({ + children, + className, + ...props +}: EmptyStateActionsProps) => ( +
    + {children} +
    +); +EmptyStateActions.displayName = 'EmptyStateActions'; diff --git a/packages/react-core/src/components/EmptyState/EmptyStateBody.tsx b/packages/react-core/src/components/EmptyState/EmptyStateBody.tsx index acd4f48a7f0..7fd4250d6a5 100644 --- a/packages/react-core/src/components/EmptyState/EmptyStateBody.tsx +++ b/packages/react-core/src/components/EmptyState/EmptyStateBody.tsx @@ -1,17 +1,16 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; export interface EmptyStateBodyProps extends React.HTMLProps { - /** Content rendered inside the EmptyState */ + /** Content rendered inside the empty state body */ children?: React.ReactNode; - /** Additional classes added to the EmptyState */ + /** Additional classes added to the empty state body */ className?: string; } export const EmptyStateBody: React.FunctionComponent = ({ children, - className = '', + className, ...props }: EmptyStateBodyProps) => (
    diff --git a/packages/react-core/src/components/EmptyState/EmptyStateFooter.tsx b/packages/react-core/src/components/EmptyState/EmptyStateFooter.tsx new file mode 100644 index 00000000000..44f3e90052b --- /dev/null +++ b/packages/react-core/src/components/EmptyState/EmptyStateFooter.tsx @@ -0,0 +1,20 @@ +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; + +export interface EmptyStateFooterProps extends React.HTMLProps { + /** Content rendered inside the empty state footer */ + children?: React.ReactNode; + /** Additional classes added to the empty state footer */ + className?: string; +} + +export const EmptyStateFooter: React.FunctionComponent = ({ + children, + className, + ...props +}: EmptyStateFooterProps) => ( +
    + {children} +
    +); +EmptyStateFooter.displayName = 'EmptyStateFooter'; diff --git a/packages/react-core/src/components/EmptyState/EmptyStateHeader.tsx b/packages/react-core/src/components/EmptyState/EmptyStateHeader.tsx new file mode 100644 index 00000000000..a0aa6658c44 --- /dev/null +++ b/packages/react-core/src/components/EmptyState/EmptyStateHeader.tsx @@ -0,0 +1,45 @@ +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; +import { EmptyStateIcon } from './EmptyStateIcon'; + +export enum EmptyStateHeadingLevel { + h1 = 'h1', + h2 = 'h2', + h3 = 'h3', + h4 = 'h4', + h5 = 'h5', + h6 = 'h6' +} + +export interface EmptyStateHeaderProps extends React.HTMLProps { + /** Additional classes added to the empty state header */ + className?: string; + /** Additional classes added to the title inside empty state header */ + titleClassName?: string; + /** Text of the title inside empty state header, will be wrapped in headingLevel */ + titleText?: React.ReactNode; + /** Empty state icon element to be rendered. Can also be a spinner component */ + icon?: React.ComponentType; + /** The heading level to use, default is h1 */ + headingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; +} + +export const EmptyStateHeader: React.FunctionComponent = ({ + className, + titleClassName, + titleText, + headingLevel: HeadingLevel = EmptyStateHeadingLevel.h1, + icon: Icon, + ...props +}: EmptyStateHeaderProps) => ( +
    + {Icon && } + {titleText && ( +
    + {titleText} +
    + )} +
    +); + +EmptyStateHeader.displayName = 'EmptyStateHeader'; diff --git a/packages/react-core/src/components/EmptyState/EmptyStateIcon.tsx b/packages/react-core/src/components/EmptyState/EmptyStateIcon.tsx index be32ef67903..4364fb5e321 100644 --- a/packages/react-core/src/components/EmptyState/EmptyStateIcon.tsx +++ b/packages/react-core/src/components/EmptyState/EmptyStateIcon.tsx @@ -1,38 +1,25 @@ -import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/EmptyState/empty-state'; - -export interface IconProps extends Omit, 'size'> { - /** Changes the color of the icon. */ - color?: string; -} - -export interface EmptyStateIconProps extends IconProps { - /** Additional classes added to the EmptyState */ +import { Spinner } from '../Spinner'; +export interface EmptyStateIconProps { + /** Additional classes added to the empty state icon */ className?: string; - /** Icon component to be rendered inside the EmptyState on icon variant - * Usually a CheckCircleIcon, ExclamationCircleIcon, LockIcon, PlusCircleIcon, RocketIcon - * SearchIcon, or WrenchIcon */ - icon?: React.ComponentType; - /** Component to be rendered inside the EmptyState on container variant */ - component?: React.ComponentType; - /** Adds empty state icon variant styles */ - variant?: 'icon' | 'container'; + /** Icon component to be rendered. Can also be a spinner component */ + icon: React.ComponentType; } +const isSpinner = (icon: React.ReactElement) => icon.type === Spinner; + export const EmptyStateIcon: React.FunctionComponent = ({ - className = '', + className, icon: IconComponent, - component: AnyComponent, - variant = 'icon', ...props }: EmptyStateIconProps) => { - const classNames = css(styles.emptyStateIcon, className); - return variant === 'icon' ? ( -
    } className={"''"} />); - expect(view).toMatchSnapshot(); + const { asFragment } = render(ReactNode} className={"''"} />); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStateIcon.test.tsx b/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStateIcon.test.tsx index 1feb3496d72..ff74157220e 100644 --- a/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStateIcon.test.tsx +++ b/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStateIcon.test.tsx @@ -1,36 +1,18 @@ /** * This test was generated */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { UserIcon } from '@patternfly/react-icons' +import { render } from '@testing-library/react'; +import UserIcon from '@patternfly/react-icons/dist/esm/icons/user-icon'; import { EmptyStateIcon } from '../../EmptyStateIcon'; // any missing imports can usually be resolved by adding them here -import {} from '../..'; +import { Spinner } from '../../../Spinner/Spinner'; + it('EmptyStateIcon should match snapshot (auto-generated)', () => { - const view = shallow( - - ); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); it('EmptyStateIcon should match snapshot for variant container', () => { - const view = shallow( -
    Component
    } - variant={'container'} - /> - ); - expect(view).toMatchSnapshot(); + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStatePrimary.test.tsx b/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStatePrimary.test.tsx deleted file mode 100644 index 783027ed571..00000000000 --- a/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStatePrimary.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { EmptyStatePrimary } from '../../EmptyStatePrimary'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('EmptyStatePrimary should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStateSecondaryActions.test.tsx b/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStateSecondaryActions.test.tsx deleted file mode 100644 index 7f24208d1f0..00000000000 --- a/packages/react-core/src/components/EmptyState/__tests__/Generated/EmptyStateSecondaryActions.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { EmptyStateSecondaryActions } from '../../EmptyStateSecondaryActions'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('EmptyStateSecondaryActions should match snapshot (auto-generated)', () => { - const view = shallow(ReactNode} className={"''"} />); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyState.test.tsx.snap b/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyState.test.tsx.snap deleted file mode 100644 index 7c5a8cd0191..00000000000 --- a/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyState.test.tsx.snap +++ /dev/null @@ -1,15 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`EmptyState should match snapshot (auto-generated) 1`] = ` -
    -
    -
    - ReactNode -
    -
    -
    -`; diff --git a/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateActions.test.tsx.snap b/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateActions.test.tsx.snap new file mode 100644 index 00000000000..db09db8c168 --- /dev/null +++ b/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateActions.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EmptyStateActions should match snapshot (auto-generated) 1`] = ` + +
    + ReactNode +
    +
    +`; diff --git a/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateBody.test.tsx.snap b/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateBody.test.tsx.snap index 0f62a993c7e..071cf048dff 100644 --- a/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateBody.test.tsx.snap +++ b/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateBody.test.tsx.snap @@ -1,11 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EmptyStateBody should match snapshot (auto-generated) 1`] = ` -
    -
    - ReactNode + +
    +
    + ReactNode +
    -
    + `; diff --git a/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateIcon.test.tsx.snap b/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateIcon.test.tsx.snap index 90c41956d8a..93ced2acd39 100644 --- a/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateIcon.test.tsx.snap +++ b/packages/react-core/src/components/EmptyState/__tests__/Generated/__snapshots__/EmptyStateIcon.test.tsx.snap @@ -1,20 +1,60 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EmptyStateIcon should match snapshot (auto-generated) 1`] = ` -
    + `; -exports[`EmptyState Main 1`] = ` -
    +exports[`EmptyState Header with icon 1`] = ` +
    - + <svg + aria-hidden="true" + class="pf-v6-svg" + fill="currentColor" + height="1em" + role="img" + viewBox="0 0 32 32" + width="1em" + > + <path + d="M26.5 1H12a1.001 1.001 0 0 0-.708.294L4.294 8.292A1.001 1.001 0 0 0 4 9v20.5c0 .827.673 1.5 1.5 1.5h21c.827 0 1.5-.673 1.5-1.5v-27c0-.827-.673-1.5-1.5-1.5ZM11 4.414V8H7.414L11 4.414ZM26 29H6V10h5.5c.827 0 1.5-.673 1.5-1.5V3h13v26Z" + /> + </svg> + </div> + <div + class="pf-v6-c-empty-state__title" > - HTTP Proxies - - - Defining HTTP Proxies that exist on your network allows you to perform various actions through those proxies. - -
    +
    + +`; + +exports[`EmptyState Main 1`] = ` + +
    +
    - New HTTP Proxy - - -
    +
    - Learn more about this in the documentation. - - + Defining HTTP Proxies that exist on your network allows you to perform various actions through those proxies. +
    + +
    - +
    `; exports[`EmptyState Main variant large 1`] = ` -
    +
    - - EmptyState large - +
    +
    +

    + EmptyState large +

    +
    +
    +
    - + `; exports[`EmptyState Main variant small 1`] = ` -
    +
    - - EmptyState small - +
    +
    +

    + EmptyState small +

    +
    +
    +
    - + `; exports[`EmptyState Main variant xs 1`] = ` -
    +
    - - EmptyState small - +
    +
    +

    + EmptyState extra small +

    +
    +
    +
    - + `; diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyState.md b/packages/react-core/src/components/EmptyState/examples/EmptyState.md index 8e14797bbed..31418592612 100644 --- a/packages/react-core/src/components/EmptyState/examples/EmptyState.md +++ b/packages/react-core/src/components/EmptyState/examples/EmptyState.md @@ -1,242 +1,50 @@ --- id: Empty state section: components -cssPrefix: pf-c-empty-state -propComponents: ['EmptyState', 'EmptyStateBody', 'EmptyStateIcon', 'EmptyStateSecondaryActions'] +cssPrefix: pf-v6-c-empty-state +propComponents: ['EmptyState', 'EmptyStateBody', 'EmptyStateFooter', 'EmptyStateActions'] --- + +import { useState } from 'react'; import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; ## Examples ### Basic -```js -import React from 'react'; -import { - Title, - Button, - EmptyState, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions -} from '@patternfly/react-core'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; - - - - Empty state - - - This represents an the empty state pattern in Patternfly 4. Hopefully it's simple enough to use but flexible - enough to meet a variety of needs. - - - - - - - - - - - +```ts file="EmptyStateBasic.tsx" ``` ### Extra small -```js -import React from 'react'; -import { - Title, - Button, - EmptyState, - EmptyStateVariant, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions -} from '@patternfly/react-core'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; - - - Empty state - - - This represents an the empty state pattern in Patternfly 4. Hopefully it's simple enough to use but flexible - enough to meet a variety of needs. - - - - - - - - - - +```ts file="EmptyStateExtraSmall.tsx" ``` ### Small -```js -import React from 'react'; -import { - Title, - Button, - EmptyState, - EmptyStateVariant, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions -} from '@patternfly/react-core'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; - - - - Empty state - - - This represents an the empty state pattern in Patternfly 4. Hopefully it's simple enough to use but flexible - enough to meet a variety of needs. - - - - - - - - - - - +```ts file="EmptyStateSmall.tsx" ``` ### Large -```js -import React from 'react'; -import { - Title, - Button, - EmptyState, - EmptyStateVariant, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions -} from '@patternfly/react-core'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; - - - - Empty state - - - This represents an the empty state pattern in Patternfly 4. Hopefully it's simple enough to use but flexible - enough to meet a variety of needs. - - - - - - - - - - - +```ts file="EmptyStateLarge.tsx" ``` ### Extra large -```js -import React from 'react'; -import { - Title, - Button, - EmptyState, - EmptyStateVariant, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions -} from '@patternfly/react-core'; -import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; - - - - Empty state - - - This represents an the empty state pattern in Patternfly 4. Hopefully it's simple enough to use but flexible - enough to meet a variety of needs. - - - - - - - - - - - +```ts file="EmptyStateExtraLarge.tsx" +``` + +### With status +```ts file="EmptyStateWithStatus.tsx" ``` ### Spinner -```js -import React from 'react'; -import { - Title, - Button, - EmptyState, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions -} from '@patternfly/react-core'; - - -EmptyStateSpinner = () => { - const Spinner = () => ( - - - - - - ) - return ( - - - - Loading - - - ); -} + +```ts file="EmptyStateSpinner.tsx" ``` ### No match found -```js -import React from 'react'; -import { - Title, - Button, - EmptyState, - EmptyStatePrimary, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions -} from '@patternfly/react-core'; -import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; - - - - - No results found - - - No results match the filter criteria. Clear all filters and try again. - - - - - +```ts file="EmptyStateNoMatchFound.tsx" ``` diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateBasic.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateBasic.tsx new file mode 100644 index 00000000000..5d9ec5f69aa --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateBasic.tsx @@ -0,0 +1,24 @@ +import { Button, EmptyState, EmptyStateBody, EmptyStateActions, EmptyStateFooter } from '@patternfly/react-core'; +import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; + +export const EmptyStateBasic: React.FunctionComponent = () => ( + + + This represents the empty state pattern in PatternFly. Hopefully it's simple enough to use but flexible enough to + meet a variety of needs. + + + + + + + + + + + + + + + +); diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateExtraLarge.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateExtraLarge.tsx new file mode 100644 index 00000000000..df77962cc9d --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateExtraLarge.tsx @@ -0,0 +1,31 @@ +import { + Button, + EmptyState, + EmptyStateVariant, + EmptyStateBody, + EmptyStateActions, + EmptyStateFooter +} from '@patternfly/react-core'; +import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; + +export const EmptyStateExtraLarge: React.FunctionComponent = () => ( + + + This represents the empty state pattern in PatternFly. Hopefully it's simple enough to use but flexible enough to + meet a variety of needs. + + + + + + + + + + + + + + + +); diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateExtraSmall.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateExtraSmall.tsx new file mode 100644 index 00000000000..68394ae4481 --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateExtraSmall.tsx @@ -0,0 +1,25 @@ +import { + Button, + EmptyState, + EmptyStateVariant, + EmptyStateBody, + EmptyStateActions, + EmptyStateFooter +} from '@patternfly/react-core'; +import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; + +export const EmptyStateExtraSmall: React.FunctionComponent = () => ( + + This represents an the empty state pattern in PatternFly. The icon is optional. + + + + + + + + + + + +); diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateLarge.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateLarge.tsx new file mode 100644 index 00000000000..a978914053a --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateLarge.tsx @@ -0,0 +1,31 @@ +import { + Button, + EmptyState, + EmptyStateVariant, + EmptyStateBody, + EmptyStateActions, + EmptyStateFooter +} from '@patternfly/react-core'; +import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; + +export const EmptyStateLarge: React.FunctionComponent = () => ( + + + This represents the empty state pattern in PatternFly. Hopefully it's simple enough to use but flexible enough to + meet a variety of needs. + + + + + + + + + + + + + + + +); diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateNoMatchFound.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateNoMatchFound.tsx new file mode 100644 index 00000000000..3c5e91d6161 --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateNoMatchFound.tsx @@ -0,0 +1,13 @@ +import { Button, EmptyState, EmptyStateBody, EmptyStateFooter, EmptyStateActions } from '@patternfly/react-core'; +import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; + +export const EmptyStateNoMatchFound: React.FunctionComponent = () => ( + + No results match the filter criteria. Clear all filters and try again. + + + + + + +); diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateSmall.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateSmall.tsx new file mode 100644 index 00000000000..faa4bce82ba --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateSmall.tsx @@ -0,0 +1,31 @@ +import { + Button, + EmptyState, + EmptyStateVariant, + EmptyStateBody, + EmptyStateActions, + EmptyStateFooter +} from '@patternfly/react-core'; +import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon'; + +export const EmptyStateSmall: React.FunctionComponent = () => ( + + + This represents the empty state pattern in PatternFly. Hopefully it's simple enough to use but flexible enough to + meet a variety of needs. + + + + + + + + + + + + + + + +); diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateSpinner.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateSpinner.tsx new file mode 100644 index 00000000000..c9e0632e839 --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateSpinner.tsx @@ -0,0 +1,5 @@ +import { EmptyState, Spinner } from '@patternfly/react-core'; + +export const EmptyStateSpinner: React.FunctionComponent = () => ( + +); diff --git a/packages/react-core/src/components/EmptyState/examples/EmptyStateWithStatus.tsx b/packages/react-core/src/components/EmptyState/examples/EmptyStateWithStatus.tsx new file mode 100644 index 00000000000..c9b3a9bceca --- /dev/null +++ b/packages/react-core/src/components/EmptyState/examples/EmptyStateWithStatus.tsx @@ -0,0 +1,61 @@ +import { useState } from 'react'; +import { + EmptyState, + EmptyStateBody, + EmptyStateFooter, + EmptyStateActions, + EmptyStateStatus, + Button +} from '@patternfly/react-core'; + +export const EmptyStateWithStatus: React.FunctionComponent = () => { + const [status, setStatus] = useState(EmptyStateStatus.success); + + const toggleStatus = () => { + interface StatusToggleMap { + [status: string]: EmptyStateStatus; + } + + const statusToggleMap: StatusToggleMap = { + success: EmptyStateStatus.danger, + danger: EmptyStateStatus.warning, + warning: EmptyStateStatus.info, + info: EmptyStateStatus.custom, + custom: EmptyStateStatus.success + }; + + setStatus((prevStatus: EmptyStateStatus) => statusToggleMap[prevStatus]); + }; + + const titleMap = { + success: "You're all set", + danger: "You're not set", + warning: "You're probably not set", + info: 'You might be set', + custom: "You're custom" + }; + + return ( + + + This represents an the empty state pattern in PatternFly. Hopefully it's simple enough to use but flexible + enough to meet a variety of needs. + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/react-core/src/components/EmptyState/index.ts b/packages/react-core/src/components/EmptyState/index.ts index 6deb697afbf..e30d2d2f3a4 100644 --- a/packages/react-core/src/components/EmptyState/index.ts +++ b/packages/react-core/src/components/EmptyState/index.ts @@ -1,5 +1,4 @@ export * from './EmptyState'; export * from './EmptyStateBody'; -export * from './EmptyStateIcon'; -export * from './EmptyStateSecondaryActions'; -export * from './EmptyStatePrimary'; +export * from './EmptyStateFooter'; +export * from './EmptyStateActions'; diff --git a/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx b/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx index 1c6b376a182..ed4e612982c 100644 --- a/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx +++ b/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx @@ -1,65 +1,140 @@ -import * as React from 'react'; +import { Component, createRef } from 'react'; import styles from '@patternfly/react-styles/css/components/ExpandableSection/expandable-section'; import { css } from '@patternfly/react-styles'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import lineClamp from '@patternfly/react-tokens/dist/esm/c_expandable_section_m_truncate__content_LineClamp'; +import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon'; import { PickOptional } from '../../helpers/typeUtils'; +import { debounce } from '../../helpers/util'; +import { getResizeObserver } from '../../helpers/resizeObserver'; +import { GenerateId } from '../../helpers'; +import { Button } from '../Button'; -export interface ExpandableSectionProps extends React.HTMLProps { - /** Content rendered inside the Expandable Component */ +export enum ExpandableSectionVariant { + default = 'default', + truncate = 'truncate' +} + +/** The main expandable section component. */ + +export interface ExpandableSectionProps extends Omit, 'onToggle'> { + /** Content rendered inside the expandable section. */ children?: React.ReactNode; - /** Additional classes added to the Expandable Component */ + /** Additional classes added to the expandable section. */ className?: string; - /** Flag to indicate if the content is expanded */ + /** Id of the content of the expandable section. When passing in the isDetached property, this + * property's value should match the contentId property of the expandable section toggle sub-component. + */ + contentId?: string; + /** Id of the toggle of the expandable section, which provides an accessible name to the + * expandable section content via the aria-labelledby attribute. When the isDetached property + * is also passed in, the value of this property must match the toggleId property of the + * expandable section toggle sub-component. + */ + toggleId?: string; + /** Display size variant. Set to "lg" for disclosure styling. */ + displaySize?: 'default' | 'lg'; + /** Flag indicating that the expandable section and expandable toggle are detached from one another. */ + isDetached?: boolean; + /** Flag to indicate if the content is expanded. */ isExpanded?: boolean; - /** Text that appears in the attached toggle */ + /** Flag to indicate if the content is indented. */ + isIndented?: boolean; + /** Flag to indicate the width of the component is limited. Set to "true" for disclosure styling. */ + isWidthLimited?: boolean; + /** Callback function to toggle the expandable section. Detached expandable sections should + * use the onToggle property of the expandable section toggle sub-component. + */ + onToggle?: (event: React.MouseEvent, isExpanded: boolean) => void; + /** React node that appears in the attached toggle in place of the toggleText property. + * Can also be a function that receives the expanded state and returns a React node. + */ + toggleContent?: React.ReactNode | ((isExpanded: boolean) => React.ReactNode); + /** Text that appears in the attached toggle. */ toggleText?: string; - /** Text that appears in the attached toggle when expanded (will override toggleText if both are specified; used for uncontrolled expandable with dynamic toggle text) */ - toggleTextExpanded?: string; - /** Text that appears in the attached toggle when collapsed (will override toggleText if both are specified; used for uncontrolled expandable with dynamic toggle text) */ + /** Text that appears in the attached toggle when collapsed (will override toggleText if + * both are specified; used for uncontrolled expandable with dynamic toggle text). + */ toggleTextCollapsed?: string; - /** Callback function to toggle the expandable content. Detached expandable sections should use the onToggle property of ExpandableSectionToggle. */ - onToggle?: (isExpanded: boolean) => void; - /** Forces active state */ - isActive?: boolean; - /** Indicates the expandable section has a detached toggle */ - isDetached?: boolean; - /** ID of the content of the expandable section */ - contentId?: string; - /** Display size variant. Set to large for disclosure styling. */ - displaySize?: 'default' | 'large'; - /** Flag to indicate the width of the component is limited. Set to true for disclosure styling. */ - isWidthLimited?: boolean; - /** Flag to indicate if the content is indented */ - isIndented?: boolean; + /** Text that appears in the attached toggle when expanded (will override toggleText if + * both are specified; used for uncontrolled expandable with dynamic toggle text). + */ + toggleTextExpanded?: string; + /** Accessible name via human readable string for the expandable section toggle. */ + toggleAriaLabel?: string; + /** Accessible name via space delimtted list of IDs for the expandable section toggle. */ + toggleAriaLabelledBy?: string; + /** Icon shown in toggle when variant is not truncated. */ + toggleIcon?: React.ReactNode; + /** Whether to show a toggle icon when variant is not truncated. If omitted, it is important to ensure the current state of the ExpandableSection is conveyed, most likely by having dynamic toggle text. */ + hasToggleIcon?: boolean; + /** Truncates the expandable content to the specified number of lines when using the + * "truncate" variant. + */ + truncateMaxLines?: number; + /** Determines the variant of the expandable section. When passing in "truncate" as the + * variant, the expandable content will be truncated after 3 lines by default. + */ + variant?: 'default' | 'truncate'; + /** Sets the direction of the expandable animation when isDetached is true. If this prop is not passed, + * animation will not occur. + */ + direction?: 'up' | 'down'; + /** The HTML element to use for the toggle wrapper. Can be 'div' (default) or any heading level. + * When using heading elements, the button will be rendered inside the heading for proper semantics. + * This is useful when the toggle text should function as a heading in the document structure. + */ + toggleWrapper?: 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } interface ExpandableSectionState { isExpanded: boolean; + hasToggle: boolean; + previousWidth: number; } -export class ExpandableSection extends React.Component { +const directionClassMap = { + up: styles.modifiers.expandTop, + down: styles.modifiers.expandBottom +}; + +const setLineClamp = (lines: number, element: HTMLDivElement) => { + if (!element || lines < 1) { + return; + } + + element.style.setProperty(lineClamp.name, lines.toString()); +}; + +class ExpandableSection extends Component { static displayName = 'ExpandableSection'; + constructor(props: ExpandableSectionProps) { super(props); this.state = { - isExpanded: props.isExpanded + isExpanded: props.isExpanded, + hasToggle: true, + previousWidth: undefined }; } + expandableContentRef = createRef(); + observer: any = () => {}; + static defaultProps: PickOptional = { className: '', toggleText: '', toggleTextExpanded: '', toggleTextCollapsed: '', + toggleAriaLabel: undefined, + toggleAriaLabelledBy: undefined, // eslint-disable-next-line @typescript-eslint/no-unused-vars - onToggle: (isExpanded): void => undefined, - isActive: false, + onToggle: (event, isExpanded): void => undefined, isDetached: false, displaySize: 'default', isWidthLimited: false, isIndented: false, - contentId: '' + variant: 'default' }; private calculateToggleText( @@ -77,15 +152,73 @@ export class ExpandableSection extends React.Component { + if (this.expandableContentRef?.current) { + const maxLines = this.props.truncateMaxLines || parseInt(lineClamp.value); + const totalLines = + this.expandableContentRef.current.scrollHeight / + parseInt(getComputedStyle(this.expandableContentRef.current).lineHeight); + + this.setState({ + hasToggle: totalLines > maxLines + }); + } + }; + + resize = () => { + if (this.expandableContentRef.current) { + const { offsetWidth } = this.expandableContentRef.current; + if (this.state.previousWidth !== offsetWidth) { + this.setState({ previousWidth: offsetWidth }); + this.checkToggleVisibility(); + } + } + }; + handleResize = debounce(this.resize, 250); + render() { const { onToggle: onToggleProp, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - isActive, className, toggleText, toggleTextExpanded, toggleTextCollapsed, + toggleContent, + toggleAriaLabel, + toggleAriaLabelledBy, + toggleIcon = , + hasToggleIcon = true, children, isExpanded, isDetached, @@ -93,16 +226,30 @@ export class ExpandableSection extends React.Component { - this.setState({ isExpanded: isOpen }, () => onToggleProp(this.state.isExpanded)); + onToggle = (event, isOpen) => { + this.setState({ isExpanded: isOpen }, () => onToggleProp(event, this.state.isExpanded)); }; } @@ -113,37 +260,74 @@ export class ExpandableSection extends React.Component - {!isDetached && ( - + + {(genContentId) => ( + + {(genToggleId) => { + const uniqueContentId = contentId || genContentId; + const uniqueToggleId = toggleId || genToggleId; + + const expandableToggle = !isDetached && ( + + + + ); + + return ( +
    + {variant === ExpandableSectionVariant.default && expandableToggle} + + {variant === ExpandableSectionVariant.truncate && this.state.hasToggle && expandableToggle} +
    + ); + }} +
    )} - - +
    ); } } + +export { ExpandableSection }; diff --git a/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx b/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx index 8ed7b8fa435..2d06651d986 100644 --- a/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx +++ b/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx @@ -1,21 +1,44 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/ExpandableSection/expandable-section'; import { css } from '@patternfly/react-styles'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; +import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon'; +import { Button } from '../Button'; -export interface ExpandableSectionToggleProps extends React.HTMLProps { +/** Acts as the toggle sub-component when the main expandable section component has the isDetached + * property passed in. Allows for more custom control over the expandable section's toggle. + */ + +export interface ExpandableSectionToggleProps extends Omit, 'onToggle'> { /** Content rendered inside the expandable toggle. */ children?: React.ReactNode; /** Additional classes added to the expandable toggle. */ className?: string; + /** Id of the toggle's respective expandable section content. The value passed into this + * property should match the contentId property of the main expandable section component. + */ + contentId?: string; + /** Id of the toggle. The value passed into this property should match the aria-labelledby + * property of the main expandable section component. + */ + toggleId?: string; + /** Direction the toggle arrow should point when the expandable section is expanded. */ + direction?: 'up' | 'down'; + /** Flag to determine toggle styling when the expandable content is truncated. */ + hasTruncatedContent?: boolean; /** Flag indicating if the expandable section is expanded. */ isExpanded?: boolean; /** Callback function to toggle the expandable content. */ onToggle?: (isExpanded: boolean) => void; - /** ID of the toggle's respective expandable section content. */ - contentId?: string; - /** Direction the toggle arrow should point when the expandable section is expanded. */ - direction?: 'up' | 'down'; + /** Flag indicating that the expandable section and expandable toggle are detached from one another. */ + isDetached?: boolean; + /** Accessible name via human readable string for the expandable section toggle. */ + toggleAriaLabel?: string; + /** Accessible name via space delimtted list of IDs for the expandable section toggle. */ + toggleAriaLabelledBy?: string; + /** The HTML element to use for the toggle wrapper. Can be 'div' (default) or any heading level. + * When using heading elements, the button will be rendered inside the heading for proper semantics. + * This is useful when the toggle text should function as a heading in the document structure. + */ + toggleWrapper?: 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } export const ExpandableSectionToggle: React.FunctionComponent = ({ @@ -24,36 +47,56 @@ export const ExpandableSectionToggle: React.FunctionComponent ( -
    - -
    -); + + + + + ); +}; ExpandableSectionToggle.displayName = 'ExpandableSectionToggle'; diff --git a/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx b/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx index d58d76a8242..06d16370775 100644 --- a/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx +++ b/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx @@ -1,55 +1,308 @@ -import * as React from 'react'; -import { shallow, mount } from 'enzyme'; -import { ExpandableSection } from '../ExpandableSection'; -import { ExpandableSectionToggle } from '../ExpandableSectionToggle'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; -const props = {}; +import { ExpandableSection, ExpandableSectionVariant } from '../ExpandableSection'; +import styles from '@patternfly/react-styles/css/components/ExpandableSection/expandable-section'; +import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon'; + +const props = { contentId: 'content-id', toggleId: 'toggle-id' }; test('ExpandableSection', () => { - const view = shallow(test ); - expect(view).toMatchSnapshot(); + const { asFragment } = render(test ); + expect(asFragment()).toMatchSnapshot(); }); test('Renders ExpandableSection expanded', () => { - const view = shallow( test ); - expect(view).toMatchSnapshot(); + const { asFragment } = render( + + {' '} + test{' '} + + ); + expect(asFragment()).toMatchSnapshot(); }); -test('ExpandableSection onToggle called', () => { +test('Calls onToggle when clicked', async () => { const mockfn = jest.fn(); - const view = shallow( test ); - view - .find('button') - .at(0) - .simulate('click'); + const user = userEvent.setup(); + + render( test ); + + await user.click(screen.getByRole('button')); expect(mockfn.mock.calls).toHaveLength(1); }); -test('Renders Uncontrolled ExpandableSection', () => { - const view = shallow( test ); - expect(view).toMatchSnapshot(); +test('Does not call onToggle when not clicked', async () => { + const mockfn = jest.fn(); + const user = userEvent.setup(); + + render( + <> + test + + + ); + + await user.click(screen.getByRole('button', { name: 'Test clicker' })); + expect(mockfn).not.toHaveBeenCalled(); }); -test('Detached ExpandableSection renders successfully', () => { - const view = mount( - - - test - - - Toggle text - - +test('Renders Uncontrolled ExpandableSection', () => { + const { asFragment } = render( + + {' '} + test{' '} + ); - expect(view).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); test('Disclosure ExpandableSection', () => { - const view = shallow(test ); - expect(view).toMatchSnapshot(); + const { asFragment } = render( + + test{' '} + + ); + expect(asFragment()).toMatchSnapshot(); }); test('Renders ExpandableSection indented', () => { - const view = shallow( test ); - expect(view).toMatchSnapshot(); + const { asFragment } = render( + + {' '} + test{' '} + + ); + expect(asFragment()).toMatchSnapshot(); +}); + +test(`Does not render with ${styles.modifiers.truncate} class when variant is not passed`, () => { + render(test); + + expect(screen.getByText('test').parentElement).not.toHaveClass(styles.modifiers.truncate); +}); + +test(`Does not render with ${styles.modifiers.truncate} class when variant is not truncate`, () => { + render(test); + + expect(screen.getByText('test').parentElement).not.toHaveClass(styles.modifiers.truncate); +}); + +test(`Renders with ${styles.modifiers.truncate} class when variant is truncate`, () => { + render(test); + + expect(screen.getByText('test').parentElement).toHaveClass(styles.modifiers.truncate); +}); + +test('Renders with value passed to contentId', () => { + render( + + Test + + ); + + const wrapper = screen.getByTestId('test-id'); + const content = wrapper.querySelector('#custom-id'); + expect(content).toBeInTheDocument(); +}); + +test('Renders with value passed to toggleId', () => { + render( + + Test + + ); + + const wrapper = screen.getByTestId('test-id'); + const toggle = wrapper.querySelector('#custom-id'); + expect(toggle).toBeVisible(); +}); + +test('Renders with ARIA attributes when contentId and toggleId are passed', () => { + render( + + Test + + ); + + const wrapper = screen.getByTestId('test-id'); + + expect(wrapper).toContainHTML('aria-labelledby="toggle-id"'); + expect(wrapper).toContainHTML('aria-controls="content-id"'); +}); + +test(`Does not render with classes ${styles.modifiers.expandTop} nor ${styles.modifiers.expandBottom} by default`, () => { + render(Test content); + + expect(screen.getByText('Test content').parentElement).not.toHaveClass('pf-m-expand-top'); + expect(screen.getByText('Test content').parentElement).not.toHaveClass('pf-m-expand-bottom'); +}); + +test(`Does not render with classes ${styles.modifiers.expandTop} nor ${styles.modifiers.expandBottom} when only isDetached is true`, () => { + render(Test content); + + expect(screen.getByText('Test content').parentElement).not.toHaveClass('pf-m-expand-top'); + expect(screen.getByText('Test content').parentElement).not.toHaveClass('pf-m-expand-bottom'); +}); + +test(`Does not render with class ${styles.modifiers.expandTop} when direction="up" and isDetached is false`, () => { + render(Test content); + + expect(screen.getByText('Test content').parentElement).not.toHaveClass('pf-m-expand-top'); +}); + +test(`Does not render with class ${styles.modifiers.expandBottom} when direction="down" and isDetached is false`, () => { + render(Test content); + + expect(screen.getByText('Test content').parentElement).not.toHaveClass('pf-m-expand-bottom'); +}); + +test(`Renders with class ${styles.modifiers.expandTop} when isDetached is true and direction="up"`, () => { + render( + + Test content + + ); + + expect(screen.getByText('Test content').parentElement).toHaveClass('pf-m-expand-top'); +}); + +test(`Renders with class ${styles.modifiers.expandBottom} when isDetached is true and direction="down"`, () => { + render( + + Test content + + ); + + expect(screen.getByText('Test content').parentElement).toHaveClass('pf-m-expand-bottom'); +}); + +test('Does not render with class pf-m-detached when isDetached is true and direction is not passed', () => { + render(Test content); + + expect(screen.getByText('Test content').parentElement).not.toHaveClass('pf-m-detached'); +}); + +test('Renders with class pf-m-detached when isDetached is true and direction is passed', () => { + render( + + Test content + + ); + + expect(screen.getByText('Test content').parentElement).toHaveClass('pf-m-detached'); +}); + +test('Renders with aria-label when toggleAriaLabel is passed', () => { + render(); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Renders with aria-labelledby when toggleAriaLabelledBy is passed', () => { + render( + <> +
    Test label
    + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Renders toggleContent as a function in uncontrolled mode (collapsed)', () => { + render( + (isExpanded ? 'Hide details' : 'Show details')}> + Test content + + ); + + expect(screen.getByRole('button', { name: 'Show details' })).toBeInTheDocument(); +}); + +test('Renders toggleContent as a function in uncontrolled mode (expanded after click)', async () => { + const user = userEvent.setup(); + + render( + (isExpanded ? 'Hide details' : 'Show details')}> + Test content + + ); + + const button = screen.getByRole('button', { name: 'Show details' }); + await user.click(button); + + expect(screen.getByRole('button', { name: 'Hide details' })).toBeInTheDocument(); +}); + +test('Renders toggleContent as a function in controlled mode', () => { + render( + (isExpanded ? 'Collapse' : 'Expand')}> + Test content + + ); + + expect(screen.getByRole('button', { name: 'Collapse' })).toBeInTheDocument(); +}); + +test('Renders with default div wrapper when toggleWrapper is not specified', () => { + render(Test content); + + const toggle = screen.getByRole('button').parentElement; + expect(toggle?.tagName).toBe('DIV'); +}); + +test('Renders with h2 wrapper when toggleWrapper="h2"', () => { + render( + + Test content + + ); + + expect(screen.getByRole('heading', { level: 2 })).toBeInTheDocument(); +}); + +test('Renders with div wrapper when toggleWrapper="div"', () => { + render( + + Test content + + ); + + const toggle = screen.getByRole('button').parentElement; + expect(toggle?.tagName).toBe('DIV'); +}); + +test('Can render custom toggle icon', () => { + render( + }> + Test content + + ); + + expect(screen.getByTestId('bell-icon')).toBeInTheDocument(); +}); + +test('Does not render toggle icon when hasToggleIcon is false', () => { + render(Test content); + + const button = screen.getByRole('button'); + expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).not.toBeInTheDocument(); +}); + +test('Does not render custom toggle icon when hasToggleIcon is false', () => { + render( + } hasToggleIcon={false}> + Test content + + ); + + expect(screen.queryByTestId('bell-icon')).not.toBeInTheDocument(); +}); + +test('Renders toggle icon by default when hasToggleIcon is true', () => { + render(Test content); + + const button = screen.getByRole('button'); + expect(button.querySelector('.pf-v6-c-expandable-section__toggle-icon')).toBeInTheDocument(); }); diff --git a/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSectionToggle.test.tsx b/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSectionToggle.test.tsx new file mode 100644 index 00000000000..9757132e6fa --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/__tests__/ExpandableSectionToggle.test.tsx @@ -0,0 +1,77 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { ExpandableSectionToggle } from '../ExpandableSectionToggle'; +import styles from '@patternfly/react-styles/css/components/ExpandableSection/expandable-section'; + +test('Renders without children', () => { + render(); + + expect(screen.getByRole('button')).toBeInTheDocument(); +}); + +test('Renders with children', () => { + render(Toggle test); + + expect(screen.getByRole('button')).toHaveTextContent('Toggle test'); +}); + +test('Does not render with class pf-m-detached by default', () => { + render(Toggle test); + + expect(screen.getByTestId('test-id')).not.toHaveClass('pf-m-detached'); +}); + +test('Renders with class pf-m-detached when isDetached is true', () => { + render( + + Toggle test + + ); + + expect(screen.getByTestId('test-id')).toHaveClass('pf-m-detached'); +}); + +test('Renders with aria-label when toggleAriaLabel is passed', () => { + render(); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Renders with aria-labelledby when toggleAriaLabelledBy is passed', () => { + render( + <> +
    Test label
    + + + ); + + expect(screen.getByRole('button')).toHaveAccessibleName('Test label'); +}); + +test('Renders with default div wrapper when toggleWrapper is not specified', () => { + render(Toggle test); + + const toggle = screen.getByRole('button').parentElement; + expect(toggle?.tagName).toBe('DIV'); +}); + +test('Renders with h2 wrapper when toggleWrapper="h2"', () => { + render( + + Toggle test + + ); + + expect(screen.getByRole('heading', { level: 2 })).toBeInTheDocument(); +}); + +test('Renders with div wrapper when toggleWrapper="div"', () => { + render( + + Toggle test + + ); + + const toggle = screen.getByRole('button').parentElement; + expect(toggle?.tagName).toBe('DIV'); +}); diff --git a/packages/react-core/src/components/ExpandableSection/__tests__/Generated/ExpandableSection.test.tsx b/packages/react-core/src/components/ExpandableSection/__tests__/Generated/ExpandableSection.test.tsx deleted file mode 100644 index d009a576d1e..00000000000 --- a/packages/react-core/src/components/ExpandableSection/__tests__/Generated/ExpandableSection.test.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { ExpandableSection } from '../../ExpandableSection'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('ExpandableSection should match snapshot (auto-generated)', () => { - const view = shallow( - ReactNode} - className={"''"} - isExpanded={true} - toggleText={"''"} - toggleTextExpanded={"''"} - toggleTextCollapsed={"''"} - onToggle={(): any => undefined} - isActive={false} - /> - ); - expect(view).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/ExpandableSection/__tests__/Generated/__snapshots__/ExpandableSection.test.tsx.snap b/packages/react-core/src/components/ExpandableSection/__tests__/Generated/__snapshots__/ExpandableSection.test.tsx.snap deleted file mode 100644 index 0f8ec81b8df..00000000000 --- a/packages/react-core/src/components/ExpandableSection/__tests__/Generated/__snapshots__/ExpandableSection.test.tsx.snap +++ /dev/null @@ -1,39 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ExpandableSection should match snapshot (auto-generated) 1`] = ` -
    - - -
    -`; diff --git a/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap b/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap index 66a4977742f..9129caa2247 100644 --- a/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap +++ b/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap @@ -1,253 +1,271 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Detached ExpandableSection renders successfully 1`] = ` -Array [ - -
    - -
    -
    , - +
    - , -] -`; - -exports[`Disclosure ExpandableSection 1`] = ` -
    - -
    -
    + `; exports[`ExpandableSection 1`] = ` -
    - + -
    + `; exports[`Renders ExpandableSection expanded 1`] = ` -
    - + -
    + `; exports[`Renders ExpandableSection indented 1`] = ` -
    - + -
    + `; exports[`Renders Uncontrolled ExpandableSection 1`] = ` -
    - +
    + - + `; diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md index 5634bce10f3..cc21b7a9d82 100644 --- a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md @@ -1,180 +1,87 @@ --- id: Expandable section section: components -cssPrefix: pf-c-expandable-section +cssPrefix: pf-v6-c-expandable-section propComponents: ['ExpandableSection', 'ExpandableSectionToggle'] --- +import { useState } from 'react'; +import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; + ## Examples ### Basic -```js -import React from 'react'; -import { ExpandableSection } from '@patternfly/react-core'; - -class SimpleExpandableSection extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.onToggle = isExpanded => { - this.setState({ - isExpanded - }); - }; - } - - render() { - const { isExpanded } = this.state; - return ( - - This content is visible only when the component is expanded. - - ); - } -} +```ts file="ExpandableSectionBasic.tsx" + ``` ### Uncontrolled -```js -import React from 'react'; -import { ExpandableSection } from '@patternfly/react-core'; +```ts file="ExpandableSectionUncontrolled.tsx" - - This content is visible only when the component is expanded. -; ``` ### Uncontrolled with dynamic toggle text -```js -import React from 'react'; -import { ExpandableSection } from '@patternfly/react-core'; +```ts file="ExpandableSectionUncontrolledDynamicToggleText.tsx" + +``` + +### Uncontrolled with dynamic toggle content (function) + +Use `toggleContent` as a function to dynamically render different content based on the expanded state without managing state yourself. + +```ts file="ExpandableSectionUncontrolledDynamicToggleFunction.tsx" - - This content is visible only when the component is expanded. -; ``` ### Detached -```js -import React from 'react'; -import { ExpandableSection, ExpandableSectionToggle, Stack, StackItem } from '@patternfly/react-core'; - -class DetachedExpandableSection extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.onToggle = isExpanded => { - this.setState({ - isExpanded - }); - }; - } - - render() { - const { isExpanded } = this.state; - const contentId = 'detached-toggle-content'; - return ( - - - - This content is visible only when the component is expanded. - - - - - {isExpanded ? 'Show less' : 'Show more'} - - - - ); - } -} +When passing the `isDetached` property into ``, you must also manually pass in the same `toggleId` and `contentId` properties to both `` and ``. This will link the content to the toggle via ARIA attributes. + +By default animations will not be enabled for a detached ``. You must manually pass the `direction` property with an appropriate value based on where the expandable content is rendered. If the expandable content is above the expandable toggle, `direction="up"` must be passed like in this example. + +```ts file="ExpandableSectionDetached.tsx" + ``` ### Disclosure variation -```js -import React from 'react'; -import { ExpandableSection } from '@patternfly/react-core'; - -class DisclosureExpandableSection extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.onToggle = isExpanded => { - this.setState({ - isExpanded - }); - }; - } - - render() { - const { isExpanded } = this.state; - return ( - - This content is visible only when the component is expanded. - - ); - } -} +You can pass in the `displaySize="lg"` property for a disclosure variation styling. + +```ts file="ExpandableSectionDisclosure.tsx" + ``` -### Indented - -```js -import React from 'react'; -import { ExpandableSection } from '@patternfly/react-core'; - -class SimpleExpandableSection extends React.Component { - constructor(props) { - super(props); - this.state = { - isExpanded: false - }; - this.onToggle = isExpanded => { - this.setState({ - isExpanded - }); - }; - } - - render() { - const { isExpanded } = this.state; - return ( - - This content is visible only when the component is expanded. - - ); - } -} -``` \ No newline at end of file +### Indented expandable content + +You can indent the expandable content by passing in the `isIndented` property. This will not affect the expandable toggle. + +```ts file="ExpandableSectionIndented.tsx" + +``` + +### With custom toggle content + +By using the `toggleContent` prop, you can pass in content other than a simple string such as an icon or a badge. When passing in custom content in this way, you should not pass in any interactive element such as a button. + +```ts file="ExpandableSectionCustomToggle.tsx" + +``` + +### With heading semantics + +When the toggle text should function as a heading in the document structure, use the `toggleWrapper` prop to specify a heading element (h1-h6). This ensures proper semantic structure for screen readers and other assistive technologies. The component automatically uses a native button element when heading wrappers are used, allowing the heading styles to display properly. + +```ts file="ExpandableSectionWithHeading.tsx" + +``` + +### Truncate expansion + +By passing in `variant="truncate"`, the expandable content will be visible up to a maximum number of lines before being truncated, with the toggle revealing or hiding the truncated content. By default the expandable content will truncate after 3 lines, and this can be customized by also passing in the `truncateMaxLines` prop. + +```ts file="ExpandableSectionTruncateExpansion.tsx" + +``` diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionBasic.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionBasic.tsx new file mode 100644 index 00000000000..3fa53d6ffdc --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionBasic.tsx @@ -0,0 +1,20 @@ +import { useState } from 'react'; +import { ExpandableSection } from '@patternfly/react-core'; + +export const ExpandableSectionBasic: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + + const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => { + setIsExpanded(isExpanded); + }; + + return ( + + This content is visible only when the component is expanded. + + ); +}; diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionCustomToggle.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionCustomToggle.tsx new file mode 100644 index 00000000000..8c334c5f11c --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionCustomToggle.tsx @@ -0,0 +1,44 @@ +import { useState } from 'react'; +import { ExpandableSection, Badge, Stack, StackItem } from '@patternfly/react-core'; +import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; + +export const ExpandableSectionCustomToggle: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + + const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => { + setIsExpanded(isExpanded); + }; + + return ( + + +

    Custom Toggle Content

    +

    You can use custom content such as icons and badges in the toggle:

    + + You can also use icons + + or badges + 4 + ! + + } + onToggle={onToggle} + isExpanded={isExpanded} + > + This content is visible only when the component is expanded. + +
    + + +

    Accessibility Note

    +

    + Important: If you need the toggle text to function as a heading in the document structure, do + NOT put heading elements (h1-h6) inside the toggleContent prop, as this creates invalid HTML + structure. Instead, use the toggleWrapper prop. +

    +
    +
    + ); +}; diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDetached.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDetached.tsx new file mode 100644 index 00000000000..c3b7be561b8 --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDetached.tsx @@ -0,0 +1,33 @@ +import { useState } from 'react'; +import { ExpandableSection, ExpandableSectionToggle, Stack, StackItem } from '@patternfly/react-core'; + +export const ExpandableSectionDetached: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + + const onToggle = (isExpanded: boolean) => { + setIsExpanded(isExpanded); + }; + + const contentId = 'detached-expandable-section-content'; + const toggleId = 'detached-expandable-section-toggle'; + return ( + + + + This content is visible only when the component is expanded. + + + + + {isExpanded ? 'Show less detached example content' : 'Show more detached example content'} + + + + ); +}; diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDisclosure.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDisclosure.tsx new file mode 100644 index 00000000000..13c866ce6a2 --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDisclosure.tsx @@ -0,0 +1,24 @@ +import { useState } from 'react'; +import { ExpandableSection } from '@patternfly/react-core'; + +export const ExpandableSectionDisclosure: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + + const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => { + setIsExpanded(isExpanded); + }; + + return ( + + This content is visible only when the component is expanded. + + ); +}; diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionIndented.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionIndented.tsx new file mode 100644 index 00000000000..922d4046eef --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionIndented.tsx @@ -0,0 +1,34 @@ +import { FormEvent, useState } from 'react'; +import { ExpandableSection, Checkbox } from '@patternfly/react-core'; + +export const ExpandableSectionIndented: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(true); + const [isDisplayLgChecked, setIsDisplayLgChecked] = useState(false); + + const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => { + setIsExpanded(isExpanded); + }; + + const onDisplaySizeCheck = (_event: FormEvent, checked: boolean) => setIsDisplayLgChecked(checked); + + return ( + <> + +
    + + This content is visible only when the component is expanded. + + + ); +}; diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionTruncateExpansion.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionTruncateExpansion.tsx new file mode 100644 index 00000000000..5c8865860ee --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionTruncateExpansion.tsx @@ -0,0 +1,27 @@ +import { useState } from 'react'; +import { ExpandableSection, ExpandableSectionVariant } from '@patternfly/react-core'; + +export const ExpandableSectionTruncateExpansion: React.FunctionComponent = () => { + const [isExpanded, setIsExpanded] = useState(false); + + const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => { + setIsExpanded(isExpanded); + }; + + return ( + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque nec dignissim turpis, et tristique purus. + Phasellus efficitur ante quis dolor viverra imperdiet. Orci varius natoque penatibus et magnis dis parturient + montes, nascetur ridiculus mus. Pellentesque laoreet, sem ac elementum semper, lectus mauris vestibulum nulla, + eget volutpat massa neque vel turpis. Donec finibus enim eu leo accumsan consectetur. Praesent massa diam, + tincidunt eu dui ac, ullamcorper elementum est. Phasellus metus felis, venenatis vitae semper nec, porta a metus. + Vestibulum justo nisi, imperdiet id eleifend at, varius nec lorem. Fusce porttitor mollis nibh, ut elementum ante + commodo tincidunt. Integer tincidunt at ipsum non aliquet. + + ); +}; diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolled.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolled.tsx new file mode 100644 index 00000000000..660de9eb1f8 --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolled.tsx @@ -0,0 +1,7 @@ +import { ExpandableSection } from '@patternfly/react-core'; + +export const ExpandableSectionUncontrolled: React.FunctionComponent = () => ( + + This content is visible only when the component is expanded. + +); diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleFunction.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleFunction.tsx new file mode 100644 index 00000000000..614329918f8 --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleFunction.tsx @@ -0,0 +1,13 @@ +import { ExpandableSection } from '@patternfly/react-core'; + +export const ExpandableSectionUncontrolledDynamicToggleFunction: React.FunctionComponent = () => ( + + isExpanded + ? 'Show less uncontrolled dynamic toggle example content' + : 'Show more uncontrolled dynamic toggle example content' + } + > + This content is visible only when the component is expanded. + +); diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleText.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleText.tsx new file mode 100644 index 00000000000..6dbb40f197b --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionUncontrolledDynamicToggleText.tsx @@ -0,0 +1,10 @@ +import { ExpandableSection } from '@patternfly/react-core'; + +export const ExpandableSectionUncontrolledDynamicToggle: React.FunctionComponent = () => ( + + This content is visible only when the component is expanded. + +); diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionWithHeading.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionWithHeading.tsx new file mode 100644 index 00000000000..f2af80222fe --- /dev/null +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionWithHeading.tsx @@ -0,0 +1,89 @@ +import { useState, MouseEvent } from 'react'; +import { ExpandableSection, ExpandableSectionToggle, Stack, StackItem } from '@patternfly/react-core'; +import RhUiCheckCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-check-circle-fill-icon'; + +export const ExpandableSectionWithHeading = () => { + const [isExpanded1, setIsExpanded1] = useState(false); + const [isExpanded2, setIsExpanded2] = useState(false); + const [isExpandedDetached, setIsExpandedDetached] = useState(false); + + const onToggle1 = (_event: MouseEvent, isExpanded: boolean) => { + setIsExpanded1(isExpanded); + }; + + const onToggle2 = (_event: MouseEvent, isExpanded: boolean) => { + setIsExpanded2(isExpanded); + }; + + const onToggleDetached = (isExpanded: boolean) => { + setIsExpandedDetached(isExpanded); + }; + + return ( + + +

    Document with Expandable Sections

    +

    This demonstrates how to use expandable sections with proper heading semantics.

    + + {/* Using toggleWrapper prop for proper heading semantics */} + +

    + This content is visible only when the component is expanded. The toggle text above functions as a proper + heading in the document structure, which is important for screen readers and other assistive technologies. +

    +

    + When using the toggleWrapper prop with heading elements (h1-h6), the button is rendered inside + the heading element, maintaining proper semantic structure. +

    +
    +
    + + +

    Detached Variant with Heading

    +

    You can also use the detached variant with heading semantics:

    + + + Detached Toggle with Heading + + + +

    This is detached content that can be positioned anywhere in the DOM.

    +
    +
    + + +

    Custom Content with Heading

    +

    You can also use custom content within heading wrappers:

    + + + Custom Heading Content with Icon +
    + } + onToggle={onToggle2} + isExpanded={isExpanded2} + > +

    This expandable section uses custom content with an icon inside a heading wrapper.

    + + + + ); +}; diff --git a/packages/react-core/src/components/FileUpload/FileUpload.tsx b/packages/react-core/src/components/FileUpload/FileUpload.tsx index 38badb8a32b..7317bb31141 100644 --- a/packages/react-core/src/components/FileUpload/FileUpload.tsx +++ b/packages/react-core/src/components/FileUpload/FileUpload.tsx @@ -1,205 +1,186 @@ -import * as React from 'react'; -import Dropzone, { DropzoneProps, DropzoneInputProps, DropFileEventHandler } from 'react-dropzone'; +import { DropzoneInputProps, DropzoneOptions, FileRejection, useDropzone, ErrorCode } from 'react-dropzone'; import { FileUploadField, FileUploadFieldProps } from './FileUploadField'; import { readFile, fileReaderType } from '../../helpers/fileUtils'; +import { DropEvent } from '../../helpers/typeUtils'; import { fromEvent } from 'file-selector'; -interface DropzoneInputPropsWithRef extends DropzoneInputProps { - ref: React.RefCallback; // Working around an issue in react-dropzone 9.0.0's types. Should not be necessary in later versions. -} - -export interface FileUploadProps - extends Omit< - FileUploadFieldProps, - 'children' | 'onBrowseButtonClick' | 'onClearButtonClick' | 'isDragActive' | 'containerRef' - > { - /** Unique id for the TextArea, also used to generate ids for accessible labels. */ - id: string; - /** What type of file. Determines what is is passed to `onChange` and expected by `value` - * (a string for 'text' and 'dataURL', or a File object otherwise. */ - type?: 'text' | 'dataURL'; - /** Value of the file's contents - * (string if text file, File object otherwise) */ - value?: string | File; +export interface FileUploadProps extends Omit< + FileUploadFieldProps, + 'children' | 'onBrowseButtonClick' | 'onClearButtonClick' | 'isDragActive' | 'containerRef' +> { + /** Flag to allow editing of a text file's contents after it is selected from disk. */ + allowEditingUploadedText?: boolean; + /** Aria-label for the text area. */ + 'aria-label'?: string; + /** Text for the browse button. */ + browseButtonText?: string; + /** ID or ID's of elements that describe the browse button. Typically this should refer + * to elements such as helper text when there are file restrictions. + */ + browseButtonAriaDescribedby?: string; + /** Additional children to render after (or instead of) the file preview. */ + children?: React.ReactNode; + /** Additional classes added to the file upload container element. */ + className?: string; + /** Text for the clear button. */ + clearButtonText?: string; /** Value to be shown in the read-only filename field. */ filename?: string; - /** @deprecated A callback for when the file contents change. Please instead use onFileInputChange, onTextChange, onDataChange, onClearClick individually. */ - onChange?: ( - value: string | File, - filename: string, - event: - | React.MouseEvent // Clear button was clicked - | React.DragEvent // User dragged/dropped a file - | React.ChangeEvent // User typed in the TextArea - ) => void; - /** Change event emitted from the hidden \ field associated with the component */ - onFileInputChange?: (event: React.ChangeEvent | React.DragEvent, file: File) => void; - /** Callback for clicking on the FileUploadField text area. By default, prevents a click in the text area from opening file dialog. */ - onClick?: (event: React.MouseEvent) => void; - /** Additional classes added to the FileUpload container element. */ - className?: string; + /** Aria-label for the read-only filename field. */ + filenameAriaLabel?: string; + /** Placeholder string to display in the empty filename field. */ + filenamePlaceholder?: string; + /** Flag to hide the built-in preview of the file (where available). If true, you can use + * the children property to render an alternate preview. + */ + hideDefaultPreview?: boolean; + /** Unique id for the text area. Also used to generate ids for accessible labels. */ + id: string; /** Flag to show if the field is disabled. */ isDisabled?: boolean; - /** Flag to show if the field is read only. */ - isReadOnly?: boolean; /** Flag to show if a file is being loaded. */ isLoading?: boolean; - /** Aria-valuetext for the loading spinner */ - spinnerAriaValueText?: string; + /** Flag to show if the field is read only. */ + isReadOnly?: boolean; /** Flag to show if the field is required. */ isRequired?: boolean; + /** Callback for clicking on the file upload field text area. By default, prevents a click + * in the text area from opening file dialog. + */ + onClick?: (event: React.MouseEvent) => void; + /** Change event emitted from the hidden \ field associated with the component */ + onFileInputChange?: (event: DropEvent, file: File) => void; + /** Aria-valuetext for the loading spinner. */ + spinnerAriaValueText?: string; + /** What type of file. Determines whether 'onDataChange` is called and what is + * expected by the value property (a string for 'text' and 'dataURL', or a File object otherwise. + */ + type?: 'text' | 'dataURL'; /** Value to indicate if the field is modified to show that validation state. * If set to success, field will be modified to indicate valid state. - * If set to error, field will be modified to indicate error state. + * If set to error, field will be modified to indicate error state. */ validated?: 'success' | 'error' | 'default'; - /** Aria-label for the TextArea. */ - 'aria-label'?: string; - /** Placeholder string to display in the empty filename field */ - filenamePlaceholder?: string; - /** Aria-label for the read-only filename field */ - filenameAriaLabel?: string; - /** Text for the Browse button */ - browseButtonText?: string; - /** Text for the Clear button */ - clearButtonText?: string; - /** Flag to hide the built-in preview of the file (where available). - * If true, you can use children to render an alternate preview. */ - hideDefaultPreview?: boolean; - /** Flag to allow editing of a text file's contents after it is selected from disk */ - allowEditingUploadedText?: boolean; - /** Additional children to render after (or instead of) the file preview. */ - children?: React.ReactNode; + /** Value of the file's contents (string if text file, File object otherwise). */ + value?: string | File; // Props available in FileUpload but not FileUploadField: - /** A callback for when a selected file starts loading */ - onReadStarted?: (fileHandle: File) => void; - /** A callback for when a selected file finishes loading */ - onReadFinished?: (fileHandle: File) => void; - /** A callback for when the FileReader API fails */ - onReadFailed?: (error: DOMException, fileHandle: File) => void; /** Optional extra props to customize react-dropzone. */ - dropzoneProps?: DropzoneProps; - /** Clear button was clicked */ + dropzoneProps?: Partial; + /** Clear button was clicked. */ onClearClick?: React.MouseEventHandler; - /** Text area text changed */ - onTextChange?: (text: string) => void; /** On data changed - if type='text' or type='dataURL' and file was loaded it will call this method */ - onDataChange?: (data: string) => void; + onDataChange?: (event: DropEvent, data: string) => void; + /** A callback for when the FileReader API fails. */ + onReadFailed?: (event: DropEvent, error: DOMException, fileHandle: File) => void; + /** A callback for when a selected file finishes loading. */ + onReadFinished?: (event: DropEvent, fileHandle: File) => void; + /** A callback for when a selected file starts loading. */ + onReadStarted?: (event: DropEvent, fileHandle: File) => void; + /** Text area text changed. */ + onTextChange?: (event: React.ChangeEvent, text: string) => void; } +export { ErrorCode as DropzoneErrorCode }; // FileInvalidType, FileTooLarge, FileTooSmall, TooManyFiles + export const FileUpload: React.FunctionComponent = ({ id, type, value = type === fileReaderType.text || type === fileReaderType.dataURL ? '' : null, filename = '', children = null, - onChange = () => {}, onFileInputChange = null, onReadStarted = () => {}, onReadFinished = () => {}, onReadFailed = () => {}, onClearClick, - onClick = event => event.preventDefault(), + onClick = (event) => event.preventDefault(), onTextChange, onDataChange, dropzoneProps = {}, ...props }: FileUploadProps) => { - const onDropAccepted: DropFileEventHandler = (acceptedFiles, event) => { + const onDropAccepted = (acceptedFiles: File[], event: DropEvent) => { if (acceptedFiles.length > 0) { const fileHandle = acceptedFiles[0]; - if (event.type === 'drop') { - onFileInputChange?.(event, fileHandle); - } + onFileInputChange?.(event, fileHandle); + if (type === fileReaderType.text || type === fileReaderType.dataURL) { - onChange('', fileHandle.name, event); // Show the filename while reading - onReadStarted(fileHandle); + onReadStarted(event, fileHandle); readFile(fileHandle, type as fileReaderType) - .then(data => { - onReadFinished(fileHandle); - onChange(data as string, fileHandle.name, event); - onDataChange?.(data as string); + .then((data) => { + onReadFinished(event, fileHandle); + onDataChange?.(event, data as string); }) .catch((error: DOMException) => { - onReadFailed(error, fileHandle); - onReadFinished(fileHandle); - onChange('', '', event); // Clear the filename field on a failure - onDataChange?.(''); + onReadFailed(event, error, fileHandle); + onReadFinished(event, fileHandle); + onDataChange?.(event, ''); }); - } else { - onChange(fileHandle, fileHandle.name, event); } } dropzoneProps.onDropAccepted && dropzoneProps.onDropAccepted(acceptedFiles, event); }; - const onDropRejected: DropFileEventHandler = (rejectedFiles, event) => { - if (rejectedFiles.length > 0) { - onChange('', rejectedFiles[0].name, event); - } + const onDropRejected = (rejectedFiles: FileRejection[], event: DropEvent) => { dropzoneProps.onDropRejected && dropzoneProps.onDropRejected(rejectedFiles, event); }; - const fileInputRef = React.useRef(); - const setFileValue = (filename: string) => { - fileInputRef.current.value = filename; - }; - const onClearButtonClick = (event: React.MouseEvent) => { - onChange('', '', event); onClearClick?.(event); setFileValue(null); }; - return ( - - {({ getRootProps, getInputProps, isDragActive, open }) => { - const oldInputProps = getInputProps(); - const inputProps: DropzoneInputProps = { - ...oldInputProps, - onChange: async (e: React.ChangeEvent) => { - oldInputProps.onChange?.(e); - const files = await fromEvent(e.nativeEvent); - if (files.length === 1) { - onFileInputChange?.(e, files[0] as File); - } - } - }; + const { getRootProps, getInputProps, isDragActive, open, inputRef } = useDropzone({ + noClick: true, + multiple: false, + ...dropzoneProps, + onDropAccepted, + onDropRejected + }); + + const setFileValue = (filename: string) => { + inputRef.current.value = filename; + }; - return ( - event.preventDefault() - })} - tabIndex={null} // Omit the unwanted tabIndex from react-dropzone's getRootProps - id={id} - type={type} - filename={filename} - value={value} - onChange={onChange} - isDragActive={isDragActive} - onBrowseButtonClick={open} - onClearButtonClick={onClearButtonClick} - onTextAreaClick={onClick} - onTextChange={onTextChange} - > - { - fileInputRef.current = input; - (inputProps as DropzoneInputPropsWithRef).ref(input); - }} - /> - {children} - - ); - }} - + const oldInputProps = getInputProps(); + const inputProps: DropzoneInputProps = { + ...oldInputProps, + onChange: async (e: React.ChangeEvent) => { + oldInputProps.onChange?.(e); + const files = await fromEvent(e.nativeEvent); + if (files.length === 1) { + onFileInputChange?.(e, files[0] as File); + } + } + }; + + const rootProps = getRootProps({ + ...props, + tabIndex: null, // Omit the unwanted tabIndex from react-dropzone's getRootProps + id, + type, + filename, + value, + isDragActive, + onBrowseButtonClick: open, + onClearButtonClick, + onTextAreaClick: onClick, + onTextChange, + onClick, + refKey: 'containerRef' + }); + + return ( + + + {children} + ); }; FileUpload.displayName = 'FileUpload'; diff --git a/packages/react-core/src/components/FileUpload/FileUploadField.tsx b/packages/react-core/src/components/FileUpload/FileUploadField.tsx index bb624fe6882..8be75a1b95f 100644 --- a/packages/react-core/src/components/FileUpload/FileUploadField.tsx +++ b/packages/react-core/src/components/FileUpload/FileUploadField.tsx @@ -1,95 +1,106 @@ -import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/FileUpload/file-upload'; import { css } from '@patternfly/react-styles'; -import { InputGroup } from '../InputGroup'; +import { InputGroup, InputGroupItem } from '../InputGroup'; import { TextInput } from '../TextInput'; import { Button, ButtonVariant } from '../Button'; import { TextArea, TextAreResizeOrientation } from '../TextArea'; import { Spinner, spinnerSize } from '../Spinner'; import { fileReaderType } from '../../helpers/fileUtils'; -export interface FileUploadFieldProps extends Omit, 'value' | 'onChange'> { - /** Unique id for the TextArea, also used to generate ids for accessible labels */ - id: string; - /** What type of file. Determines what is is expected by `value` - * (a string for 'text' and 'dataURL', or a File object otherwise). */ - type?: 'text' | 'dataURL'; - /** Value of the file's contents - * (string if text file, File object otherwise) */ - value?: string | File; +/** A more customizable file upload component for implementing custom logic. Drag and drop + * functionality is not built in by default. + */ + +export interface FileUploadFieldProps extends Omit, 'value'> { + /** Flag to allow editing of a text file's contents after it is selected from disk. */ + allowEditingUploadedText?: boolean; + /** Aria-label for the text area. */ + 'aria-label'?: string; + /** Text for the browse button. */ + browseButtonText?: string; + /** ID or ID's of elements that describe the browse button. Typically this should refer + * to elements such as helper text when there are file restrictions. + */ + browseButtonAriaDescribedby?: string; + /** Additional children to render after (or instead of) the file preview. */ + children?: React.ReactNode; + /** Additional classes added to the file upload field container element. */ + className?: string; + /** Text for the clear button. */ + clearButtonText?: string; /** Value to be shown in the read-only filename field. */ filename?: string; - /** A callback for when the TextArea value changes. */ - onChange?: ( - value: string, - filename: string, - event: - | React.ChangeEvent // User typed in the TextArea - | React.MouseEvent // User clicked Clear button - ) => void; - /** Additional classes added to the FileUploadField container element. */ - className?: string; + /** Aria-label for the read-only filename field. */ + filenameAriaLabel?: string; + /** Placeholder string to display in the empty filename field. */ + filenamePlaceholder?: string; + /** Flag to hide the built-in preview of the file (where available). If true, you can use + * the children property to render an alternate preview. + */ + hideDefaultPreview?: boolean; + /** Unique id for the text area. Also used to generate ids for accessible labels. */ + id: string; + /** Name property for the text input. */ + name?: string; + /** Flag to disable the browse button. */ + isBrowseButtonDisabled?: boolean; + /** Flag to disable the clear button. */ + isClearButtonDisabled?: boolean; /** Flag to show if the field is disabled. */ isDisabled?: boolean; - /** Flag to show if the field is read only. */ - isReadOnly?: boolean; /** Flag to show if a file is being loaded. */ isLoading?: boolean; - /** Aria-valuetext for the loading spinner */ - spinnerAriaValueText?: string; + /** Flag to show if the field is read only. */ + isReadOnly?: boolean; /** Flag to show if the field is required. */ isRequired?: boolean; + /** Aria-valuetext for the loading spinner. */ + spinnerAriaValueText?: string; + /** What type of file. Determines what is is expected by the value property (a string for + * 'text' and 'dataURL', or a File object otherwise). + */ + type?: 'text' | 'dataURL'; /** Value to indicate if the field is modified to show that validation state. * If set to success, field will be modified to indicate valid state. * If set to error, field will be modified to indicate error state. */ validated?: 'success' | 'error' | 'default'; - /** Aria-label for the TextArea. */ - 'aria-label'?: string; - /** Placeholder string to display in the empty filename field */ - filenamePlaceholder?: string; - /** Aria-label for the read-only filename field */ - filenameAriaLabel?: string; - /** Text for the Browse button */ - browseButtonText?: string; - /** Text for the Clear button */ - clearButtonText?: string; - /** Flag to disable the Clear button */ - isClearButtonDisabled?: boolean; - /** Flag to hide the built-in preview of the file (where available). - * If true, you can use children to render an alternate preview. */ - hideDefaultPreview?: boolean; - /** Flag to allow editing of a text file's contents after it is selected from disk */ - allowEditingUploadedText?: boolean; - /** Additional children to render after (or instead of) the file preview. */ - children?: React.ReactNode; + /** Value of the file's contents (string if text file, File object otherwise). */ + value?: string | File; // Props available in FileUploadField but not FileUpload: - /** A callback for when the Browse button is clicked. */ + /** A reference object to attach to the file upload field container element. */ + containerRef?: React.Ref; + /** Flag to show if a file is being dragged over the file upload field. */ + isDragActive?: boolean; + /** A callback for when the browse button is clicked. */ onBrowseButtonClick?: (event: React.MouseEvent) => void; - /** A callback for when the Clear button is clicked. */ + /** A callback for when the clear button is clicked. */ onClearButtonClick?: (event: React.MouseEvent) => void; - /** A callback from when the text area is clicked. Can also be set via the onClick property of FileUpload. */ + /** Callback for when focus is lost on the text area field. */ + onTextAreaBlur?: (event?: any) => void; + /** A callback for when the text area is clicked. Can also be set via the onClick property + * of the file upload component. */ onTextAreaClick?: (event: React.MouseEvent) => void; - /** Flag to show if a file is being dragged over the field */ - isDragActive?: boolean; - /** A reference object to attach to the FileUploadField container element. */ - containerRef?: React.Ref; - /** Text area text changed */ - onTextChange?: (text: string) => void; + /** Text area text changed. */ + onTextChange?: (event: React.ChangeEvent, text: string) => void; + /** Placeholder string to display in the empty text area field. */ + textAreaPlaceholder?: string; } export const FileUploadField: React.FunctionComponent = ({ id, + name, type, value = '', filename = '', - onChange = () => {}, onBrowseButtonClick = () => {}, onClearButtonClick = () => {}, onTextAreaClick, onTextChange, + onTextAreaBlur, + textAreaPlaceholder = '', className = '', isDisabled = false, isReadOnly = false, @@ -102,7 +113,9 @@ export const FileUploadField: React.FunctionComponent = ({ filenamePlaceholder = 'Drag a file here or browse to upload', filenameAriaLabel = filename ? 'Read only filename' : filenamePlaceholder, browseButtonText = 'Browse...', + browseButtonAriaDescribedby, clearButtonText = 'Clear', + isBrowseButtonDisabled = false, isClearButtonDisabled = !filename && !value, containerRef = null as React.Ref, allowEditingUploadedText = false, @@ -111,9 +124,8 @@ export const FileUploadField: React.FunctionComponent = ({ ...props }: FileUploadFieldProps) => { - const onTextAreaChange = (newValue: string, event: React.ChangeEvent) => { - onChange(newValue, filename, event); - onTextChange?.(newValue); + const onTextAreaChange = (event: React.ChangeEvent, newValue: string) => { + onTextChange?.(event, newValue); }; return (
    = ({ >
    - - - + + + + + + + + +
    -
    - {!hideDefaultPreview && type === fileReaderType.text && ( - - -`; - -exports[`disabled text input using isDisabled 1`] = ` - - -`; - -exports[`horizontally resizable text area 1`] = ` - - -`; - -exports[`invalid text area 1`] = ` - - -`; - -exports[`read only text input using isReadOnly 1`] = ` - - -`; - -exports[`read only text input using readOnly 1`] = ` - - -`; - -exports[`simple text input 1`] = ` - - -`; - -exports[`validated text area error 1`] = ` - - -`; - -exports[`validated text area success 1`] = ` - - -`; - -exports[`validated text area warning 1`] = ` - - -`; - -exports[`vertically resizable text area 1`] = ` - - + + `; diff --git a/packages/react-core/src/components/TextArea/examples/TextArea.md b/packages/react-core/src/components/TextArea/examples/TextArea.md index af86fe3b362..a3dd633aa64 100644 --- a/packages/react-core/src/components/TextArea/examples/TextArea.md +++ b/packages/react-core/src/components/TextArea/examples/TextArea.md @@ -1,209 +1,71 @@ --- id: Text area section: components -cssPrefix: pf-c-form-control +subsection: forms +cssPrefix: pf-v6-c-form-control propComponents: ['TextArea'] --- +import { Fragment, useRef, useState } from 'react'; + ## Examples + ### Basic -```js -import React from 'react'; -import { TextArea } from '@patternfly/react-core'; - -class SimpleTextArea extends React.Component { - constructor(props) { - super(props); - this.state = { - value: '' - }; - - this.handleTextAreaChange = value => { - this.setState({ value }); - }; - } - - render() { - const { value } = this.state; - - return