From ec23802986dab8f987b2716189882a0556f49940 Mon Sep 17 00:00:00 2001 From: Titani Date: Wed, 29 May 2024 18:04:30 -0400 Subject: [PATCH] feat(merge) merge main int v6 --- .github/actions/setup-project/action.yml | 65 + .github/promote.sh | 8 +- .github/renovate.json | 88 +- .github/stale.yml | 28 - .github/upload-preview.js | 9 +- .../workflows/add-new-issues-to-project.yml | 4 +- .github/workflows/documentation.yml | 49 + .github/workflows/extensions.yml | 4 +- .github/workflows/main.yml | 99 + .github/workflows/promote.yml | 31 +- .github/workflows/release.yml | 60 +- .github/workflows/stale.yml | 18 + CONTRIBUTING.md | 51 +- README.md | 5 +- jest.config.js | 4 +- package.json | 22 +- .../eslint-plugin-patternfly-react/README.md | 4 +- .../package.json | 1 - packages/react-charts/README.md | 19 +- packages/react-charts/package.json | 40 +- .../src/components/Chart/Chart.tsx | 9 +- .../src/components/ChartAxis/ChartAxis.tsx | 10 +- .../components/ChartBullet/ChartBullet.tsx | 40 +- .../ChartBulletComparativeErrorMeasure.tsx | 1 + .../ChartBulletComparativeMeasure.tsx | 1 + .../ChartBulletComparativeWarningMeasure.tsx | 1 + .../ChartBullet/ChartBulletGroupTitle.tsx | 5 +- .../ChartBulletPrimaryDotMeasure.tsx | 1 + .../ChartBulletPrimarySegmentedMeasure.tsx | 1 + .../ChartBulletQualitativeRange.tsx | 1 + .../ChartBullet/ChartBulletTitle.tsx | 5 +- .../ChartBullet/utils/chart-bullet-theme.ts | 5 + .../ChartCursorContainer.tsx | 6 +- .../ChartCursorTooltip/ChartCursorTooltip.tsx | 4 +- .../ChartCursorFlyout.test.tsx.snap | 8 +- .../ChartCursorTooltip.test.tsx.snap | 8 +- .../src/components/ChartDonut/ChartDonut.tsx | 14 +- .../ChartDonutThreshold.tsx | 4 +- .../ChartDonutUtilization.tsx | 1 + .../src/components/ChartGroup/ChartGroup.tsx | 3 +- .../components/ChartLegend/ChartLegend.tsx | 10 +- .../ChartLegendTooltip/ChartLegendTooltip.tsx | 3 +- .../ChartLegendTooltipContent.tsx | 15 +- .../ChartLegendTooltipLabel.tsx | 2 +- .../src/components/ChartPie/ChartPie.tsx | 1 + .../src/components/ChartPoint/ChartPoint.tsx | 2 +- .../src/components/ChartTheme/ChartTheme.ts | 47 +- .../components/ChartTheme/ChartThemeColor.ts | 4 +- .../components/ChartTheme/ChartThemeTypes.ts | 31 +- .../ChartTheme/themes/base-theme.ts | 160 +- .../ChartTheme/themes/color-theme.ts | 174 +- .../ChartTheme/themes/colors/blue-theme.ts | 11 +- .../ChartTheme/themes/colors/cyan-theme.ts | 11 +- .../ChartTheme/themes/colors/gold-theme.ts | 11 +- .../ChartTheme/themes/colors/gray-theme.ts | 11 +- .../ChartTheme/themes/colors/green-theme.ts | 11 +- .../themes/colors/multi-ordered-theme.ts | 11 +- .../themes/colors/multi-unordered-theme.ts | 11 +- .../ChartTheme/themes/colors/orange-theme.ts | 11 +- .../ChartTheme/themes/colors/purple-theme.ts | 11 +- .../themes/colors/skeleton-theme.ts | 35 + .../themes/components/axis-theme.ts | 1 + .../themes/components/bullet-theme.ts | 9 + .../themes/components/donut-theme.ts | 1 + .../components/donut-threshold-theme.ts | 2 + .../components/donut-utilization-theme.ts | 2 + .../themes/components/threshold-theme.ts | 1 + .../ChartTheme/themes/skeleton-theme.ts | 307 + .../ChartThreshold/ChartThreshold.tsx | 2 +- .../ChartThreshold/examples/ChartThreshold.md | 1 + .../__snapshots__/ChartTooltip.test.tsx.snap | 8 +- .../ChartTooltip/examples/ChartTooltip.md | 27 +- .../src/components/ChartUtils/chart-legend.ts | 3 + .../components/ChartUtils/chart-patterns.tsx | 4 +- .../ChartUtils/chart-theme-types.ts | 151 +- .../src/components/ChartUtils/chart-theme.ts | 80 +- .../components/ChartUtils/chart-tooltip.ts | 28 +- .../ResizeObserver/examples/resizeObserver.md | 1 + .../Skeletons/examples/skeletons.md | 799 + packages/react-code-editor/README.md | 27 +- packages/react-code-editor/package.json | 6 +- packages/react-core/.npmignore | 2 +- packages/react-core/CONTRIBUTING.md | 2 - packages/react-core/package.json | 17 +- packages/react-core/rollup.config.js | 7 - packages/react-core/rollup.config.mjs | 8 + .../__tests__/AccordionToggle.test.tsx | 28 + .../components/Checkbox/examples/Checkbox.md | 14 + .../Checkbox/examples/CheckboxLabelWraps.tsx | 11 + .../Checkbox/examples/CheckboxReversed.tsx | 6 + .../CodeBlock/examples/CodeBlock.md | 6 + .../CodeBlock/examples/CodeBlockBasic.tsx | 2 +- .../examples/CodeBlockExpandable.tsx | 6 +- .../src/components/DatePicker/DatePicker.tsx | 16 +- .../components/Drawer/DrawerPanelContent.tsx | 8 +- .../__tests__/DrawerPanelContent.test.tsx | 2 + .../react-core/src/components/Label/Label.tsx | 2 +- .../components/Label/__tests__/Label.test.tsx | 89 +- .../Label/examples/LabelCompact.tsx | 13 + .../src/components/MenuToggle/MenuToggle.tsx | 1 + .../__tests__/__snapshots__/Nav.test.tsx.snap | 5 +- .../NotificationDrawerGroup.tsx | 2 +- .../components/NumberInput/NumberInput.tsx | 8 +- .../react-core/src/components/Page/Page.tsx | 15 +- .../src/components/Pagination/Navigation.tsx | 24 +- .../src/components/Pagination/Pagination.tsx | 4 +- .../Pagination/PaginationOptionsMenu.tsx | 28 +- .../PaginationOptionsMenu.test.tsx.snap | 74 +- .../__tests__/PaginationOptionsMenu.test.tsx | 6 +- .../__snapshots__/Pagination.test.tsx.snap | 1468 +- .../src/components/Radio/examples/Radio.md | 11 + .../src/components/Select/Select.tsx | 7 +- .../src/components/Select/examples/Select.md | 18 + .../Select/examples/SelectMultiTypeahead.tsx | 175 +- .../examples/SelectMultiTypeaheadCheckbox.tsx | 163 +- .../SelectMultiTypeaheadCreatable.tsx | 204 +- .../Select/examples/SelectTypeahead.tsx | 182 +- .../examples/SelectTypeaheadCreatable.tsx | 190 +- .../react-core/src/components/Tabs/Tabs.tsx | 21 + .../ToggleGroup/examples/ToggleGroup.md | 41 +- .../Toolbar/__tests__/Toolbar.test.tsx | 2 + .../src/components/TreeView/TreeView.tsx | 24 +- .../src/components/TreeView/TreeViewList.tsx | 25 +- .../components/TreeView/TreeViewListItem.tsx | 23 +- .../__snapshots__/TreeViewList.test.tsx.snap | 2 + .../TreeViewListItem.test.tsx.snap | 2 + .../components/TreeView/examples/TreeView.md | 14 +- .../TreeView/examples/TreeViewCompact.tsx | 2 +- .../examples/TreeViewCompactNoBackground.tsx | 2 +- .../TreeView/examples/TreeViewGuides.tsx | 2 +- .../examples/TreeViewMultiselectable.tsx | 86 + .../examples/TreeViewSelectionExpansion.tsx | 10 +- ...fault.tsx => TreeViewSingleSelectable.tsx} | 10 +- .../examples/TreeViewWithActionItems.tsx | 9 +- .../TreeView/examples/TreeViewWithBadges.tsx | 10 +- .../examples/TreeViewWithCheckboxes.tsx | 2 +- .../examples/TreeViewWithCustomBadges.tsx | 10 +- .../TreeView/examples/TreeViewWithIcons.tsx | 1 + .../examples/TreeViewWithMemoization.tsx | 9 +- .../TreeView/examples/TreeViewWithSearch.tsx | 1 + .../src/components/Truncate/Truncate.tsx | 80 +- .../Truncate/__tests__/Truncate.test.tsx | 6 + .../src/components/Wizard/Wizard.tsx | 15 + .../src/components/Wizard/WizardBody.tsx | 18 +- .../src/components/Wizard/WizardContext.tsx | 16 +- .../src/components/Wizard/WizardNavItem.tsx | 28 +- .../Wizard/__tests__/Wizard.test.tsx | 8 +- .../src/components/Wizard/examples/Wizard.md | 30 +- .../Wizard/examples/WizardFocusOnNextBack.tsx | 16 + .../examples/WizardWithCustomFooter.tsx | 6 +- packages/react-core/src/demos/AlertGroup.md | 1 + packages/react-core/src/demos/Nav.md | 2 + .../AlertGroupToastWithNotificationDrawer.tsx | 2 +- .../src/demos/examples/Nav/NavDefault.tsx | 2 +- .../src/demos/examples/Nav/NavDrilldown.tsx | 2 +- .../src/demos/examples/Nav/NavExpandable.tsx | 2 +- .../src/demos/examples/Nav/NavGrouped.tsx | 2 +- .../src/demos/examples/Nav/NavHorizontal.tsx | 2 +- .../src/demos/examples/Nav/NavWithSubnav.tsx | 2 +- .../PasswordStrength/PasswordStrengthDemo.tsx | 24 +- .../examples/DualListSelector.md | 2 +- packages/react-docs/package.json | 6 +- .../patternfly-docs/patternfly-docs.source.js | 2 +- packages/react-drag-drop/package.json | 4 - .../next/components/DragDrop/DragButton.tsx | 27 + .../next/components/DragDrop/DragDropSort.tsx | 186 + .../next/components/DragDrop/Draggable.tsx | 58 + .../DragDrop/DraggableDataListItem.tsx | 61 + .../DraggableDualListSelectorListItem.tsx | 93 + .../next/components/DragDrop/Droppable.tsx | 27 + .../components/DragDrop/DroppableContext.ts | 6 + .../DragDrop/__tests__/DragDrop.test.tsx | 24 + .../__snapshots__/DragDrop.test.tsx.snap | 59 + .../DragDrop/examples/BasicSorting.tsx | 19 + .../examples/BasicSortingWithDragButton.tsx | 20 + .../DragDrop/examples/DataListDraggable.tsx | 38 + .../components/DragDrop/examples/DragDrop.md | 32 + .../DragDrop/examples/DragDropDemos.md | 37 + .../examples/DualListSelectorDraggable.tsx | 154 + .../src/next/components/DragDrop/index.ts | 1 + .../src/next/components/index.ts | 1 + packages/react-drag-drop/src/next/index.ts | 1 + packages/react-icons/package.json | 4 +- .../demo-app-ts/package.json | 17 +- .../demo-app-ts/src/common/State.ts | 2 +- .../DataListDemo/DataListDraggableDemo.tsx | 14 +- .../demos/DatePickerDemo/DatePickerDemo.tsx | 6 +- .../DualListSelectorBasicDemo.tsx | 6 +- .../DualListSelectorTreeDemo.tsx | 6 +- .../DualListSelectorWithActionsDemo.tsx | 6 +- .../demos/FileUploadDemo/FileUploadDemo.tsx | 7 +- .../components/demos/FormDemo/FormDemo.tsx | 2 +- .../demos/MastheadDemo/MastheadDemo.tsx | 4 +- .../components/demos/MenuDemo/MenuDemo.tsx | 22 +- .../demos/MenuDemo/MenuDrilldownDemo.tsx | 8 +- .../components/demos/ModalDemo/ModalDemo.tsx | 8 +- .../demos/ModalNextDemo/ModalNextDemo.tsx | 8 +- .../src/components/demos/NavDemo/NavDemo.tsx | 12 +- .../NotificationDrawerGroupsDemo.tsx | 6 +- .../NotificationDrawerLightweightDemo.tsx | 8 +- .../demos/NumberInputDemo/NumberInputDemo.tsx | 4 +- .../demos/PopoverDemo/PopoverDemo.tsx | 2 +- .../demos/SearchInputDemo/SearchInputDemo.tsx | 10 +- .../FilteringSelectLiveUpdateDemo.tsx | 98 + .../demos/SelectDeprecatedDemo/SelectDemo.tsx | 1457 ++ .../SelectFavoritesDemo.tsx | 325 + .../SelectDeprecatedDemo/SelectInModal.tsx | 98 + .../SelectTypeaheadFooterDemo.tsx | 86 + .../SelectValidatedDemo.tsx | 101 + .../SelectViewMoreDemo.tsx | 184 + .../SelectViewMoreGroupedDemo.tsx | 200 + .../SelectViewMoreTypeaheadGroupedDemo.tsx | 134 + .../demos/SimpleList/SimpleListDemo.tsx | 8 +- .../demos/SliderDemo/SliderDemo.tsx | 4 +- .../demos/SwitchDemo/SwitchDemo.tsx | 10 +- .../demos/TableDemo/TableCollapsibleDemo.tsx | 6 +- .../demos/TableDemo/TableComposableDemo.tsx | 60 +- .../TableDemo/TableCompoundExpandableDemo.tsx | 17 +- .../TableEditableCompoundExpandableDemo.tsx | 17 +- .../demos/TableDemo/TableEditableDemo.tsx | 120 +- .../demos/TableDemo/TableFavoritesDemo.tsx | 23 +- .../demos/TableDemo/TableRowClickDemo.tsx | 17 +- .../demos/TableDemo/TableRowWrapperDemo.tsx | 2 +- .../demos/TableDemo/TableSelectableDemo.tsx | 2 +- .../TableDemo/TableSimpleActionsDemo.tsx | 14 +- .../TabsDemo/TabsHorizontalOverflowDemo.tsx | 8 +- .../demos/TooltipDemo/TooltipDemo.tsx | 2 +- .../demos/TreeViewDemo/TreeViewDemo.tsx | 10 +- packages/react-integration/package.json | 1 - packages/react-styles/package.json | 4 +- packages/react-table/CHANGELOG.md | 3 - packages/react-table/README.md | 19 +- packages/react-table/package.json | 6 +- packages/react-table/rollup.config.js | 7 - packages/react-table/rollup.config.mjs | 8 + .../src/components/Table/TableTypes.tsx | 10 +- .../examples/TableSortableResponsive.tsx | 2 +- .../components/Table/examples/Table.md | 4 +- packages/react-templates/README.md | 19 +- packages/react-templates/package.json | 6 +- packages/react-templates/rollup.config.mjs | 8 + .../components/Dropdown/DropdownSimple.tsx | 122 + .../__tests__/DropdownSimple.test.tsx | 254 + .../DropdownSimple.test.tsx.snap | 147 + .../examples/DropdownSimpleExample.tsx | 53 + .../Dropdown/examples/DropdownTemplates.md | 36 + .../src/components/Dropdown/index.ts | 1 + .../src/components/Select/SelectTypeahead.tsx | 321 + .../Select/examples/SelectTemplates.md | 11 +- .../Select/examples/SelectTypeaheadDemo.tsx | 21 + .../src/components/Select/index.ts | 1 + .../react-templates/src/components/index.ts | 1 + packages/react-tokens/package.json | 3 +- packages/rollup.base.js | 59 - packages/rollup.base.mjs | 68 + scripts/build-single-packages.js | 86 +- scripts/generators/package/package.json.hbs | 4 +- scripts/parse-dynamic-modules.js | 159 + yarn.lock | 12285 ++++++++-------- 259 files changed, 15288 insertions(+), 8640 deletions(-) create mode 100644 .github/actions/setup-project/action.yml delete mode 100644 .github/stale.yml create mode 100644 .github/workflows/documentation.yml create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/stale.yml create mode 100644 packages/react-charts/src/components/ChartTheme/themes/colors/skeleton-theme.ts create mode 100644 packages/react-charts/src/components/ChartTheme/themes/skeleton-theme.ts create mode 100644 packages/react-charts/src/components/Skeletons/examples/skeletons.md delete mode 100644 packages/react-core/rollup.config.js create mode 100644 packages/react-core/rollup.config.mjs create mode 100644 packages/react-core/src/components/Checkbox/examples/CheckboxLabelWraps.tsx create mode 100644 packages/react-core/src/components/Checkbox/examples/CheckboxReversed.tsx create mode 100644 packages/react-core/src/components/TreeView/examples/TreeViewMultiselectable.tsx rename packages/react-core/src/components/TreeView/examples/{TreeViewDefault.tsx => TreeViewSingleSelectable.tsx} (89%) create mode 100644 packages/react-core/src/components/Wizard/examples/WizardFocusOnNextBack.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/DragButton.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/DragDropSort.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/Draggable.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/DraggableDataListItem.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/DraggableDualListSelectorListItem.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/Droppable.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/DroppableContext.ts create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/__tests__/DragDrop.test.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/__tests__/__snapshots__/DragDrop.test.tsx.snap create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/examples/BasicSorting.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/examples/BasicSortingWithDragButton.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/examples/DataListDraggable.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/examples/DragDrop.md create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/examples/DragDropDemos.md create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/examples/DualListSelectorDraggable.tsx create mode 100644 packages/react-drag-drop/src/next/components/DragDrop/index.ts create mode 100644 packages/react-drag-drop/src/next/components/index.ts create mode 100644 packages/react-drag-drop/src/next/index.ts create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/FilteringSelectLiveUpdateDemo.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectDemo.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectFavoritesDemo.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectInModal.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectTypeaheadFooterDemo.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectValidatedDemo.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectViewMoreDemo.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectViewMoreGroupedDemo.tsx create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/SelectDeprecatedDemo/SelectViewMoreTypeaheadGroupedDemo.tsx delete mode 100644 packages/react-table/rollup.config.js create mode 100644 packages/react-table/rollup.config.mjs create mode 100644 packages/react-templates/rollup.config.mjs create mode 100644 packages/react-templates/src/components/Dropdown/DropdownSimple.tsx create mode 100644 packages/react-templates/src/components/Dropdown/__tests__/DropdownSimple.test.tsx create mode 100644 packages/react-templates/src/components/Dropdown/__tests__/__snapshots__/DropdownSimple.test.tsx.snap create mode 100644 packages/react-templates/src/components/Dropdown/examples/DropdownSimpleExample.tsx create mode 100644 packages/react-templates/src/components/Dropdown/examples/DropdownTemplates.md create mode 100644 packages/react-templates/src/components/Dropdown/index.ts create mode 100644 packages/react-templates/src/components/Select/SelectTypeahead.tsx create mode 100644 packages/react-templates/src/components/Select/examples/SelectTypeaheadDemo.tsx delete mode 100644 packages/rollup.base.js create mode 100644 packages/rollup.base.mjs create mode 100644 scripts/parse-dynamic-modules.js diff --git a/.github/actions/setup-project/action.yml b/.github/actions/setup-project/action.yml new file mode 100644 index 00000000000..25f79580689 --- /dev/null +++ b/.github/actions/setup-project/action.yml @@ -0,0 +1,65 @@ +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: 20 + check-latest: true + + - name: Get Yarn configuration + id: yarn-config + shell: bash + run: | + echo "cache-directory=$(yarn cache dir)" >> $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-directory }} + key: ${{ runner.os }}-yarn-cache-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn-cache- + + - name: Install dependencies + shell: bash + run: yarn install --frozen-lockfile + + - uses: actions/cache@v4 + if: inputs.skip-build != 'true' && inputs.skip-build-cache != 'true' + id: cache-build + name: Cache build + with: + path: | + packages/*/dist + packages/*/next + packages/*/deprecated + packages/*/components + packages/react-styles/css + packages/react-core/layouts + packages/react-core/helpers + key: ${{ runner.os }}-build-${{ hashFiles('yarn.lock', '**/package.json', 'packages/**', '!**/node_modules', '!**/dist') }} + + - name: Run build + if: inputs.skip-build != 'true' && steps.cache-build.outputs.cache-hit != '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/promote.sh b/.github/promote.sh index 858a7e68dd7..3b362000571 100755 --- a/.github/promote.sh +++ b/.github/promote.sh @@ -12,10 +12,10 @@ echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc # Update their versions and changelogs according to angular commit guidelines # https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit -# if [[ ! -z "${CORE_VERSION}" ]]; then -# echo "Updating to @patternfly/patternfly: ${CORE_VERSION}" -# npm pkg set dependencies.@patternfly/patternfly=${CORE_VERSION} --workspace @patternfly/react-docs -# npm pkg set devDependencies.@patternfly/patternfly=${CORE_VERSION} --workspace @patternfly/react-core --workspace @patternfly/react-styles --workspace @patternfly/react-tokens --workspace @patternfly/react-icons +# 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 diff --git a/.github/renovate.json b/.github/renovate.json index 6008bb83845..663f5774573 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,93 +1,15 @@ { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base" + "config:recommended" ], - "enabledManagers": ["npm"], + "rangeStrategy": "bump", "packageRules": [ { - "packagePatterns": ["*"], - "excludePackagePatterns": [ - "@babel/*", - "@octokit/rest", - "@patternfly/patternfly", - "@patternfly/patternfly-a11y", - "@patternfly/documentation-framework", - "@rollup/*", - "@testing-library/jest-dom", - "@testing-library/user-event", - "@types/jest", - "@types/react", - "@types/react-dom", - "@typescript-eslint/eslint-plugin", - "@typescript-eslint/parser", - "eslint", - "eslint-plugin-prettier", - "eslint-plugin-react", - "fs-extra", - "lint-staged", - "mutation-observer", - "plop", - "prettier", - "react-dropzone", - "rollup", - "rollup-plugin-scss", - "rollup-plugin-terser", - "shx", - "surge", - "ts-patch" + "matchUpdateTypes": [ + "major" ], "enabled": false - }, - { - "groupName": "devDependencies", - "matchDatasources": ["npm"], - "automerge": true, - "matchPackagePatterns": [ - "@babel/*", - "@octokit/rest", - "@patternfly/patternfly-a11y", - "@patternfly/documentation-framework", - "@rollup/*", - "@testing-library/jest-dom", - "@testing-library/react-hooks", - "@testing-library/user-event", - "@types/jest", - "@types/react", - "@types/react-dom", - "@typescript-eslint/eslint-plugin", - "@typescript-eslint/parser", - "eslint", - "eslint-plugin-prettier", - "eslint-plugin-react", - "focus-trap", - "fs-extra", - "lint-staged", - "mutation-observer", - "plop", - "prettier", - "react-dropzone", - "rollup", - "rollup-plugin-scss", - "rollup-plugin-terser", - "shx", - "surge", - "ts-patch" - ] - }, - { - "matchDatasources": ["npm"], - "matchPackageNames": [ - "focus-trap", - "react-dropzone" - ] - }, - { - "matchDatasources": ["npm"], - "matchPackageNames": [ - "@patternfly/patternfly" - ], - "automerge": true, - "followTag": "prerelease" } ] } 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 index fafe1a2c797..7b3e534432e 100644 --- a/.github/upload-preview.js +++ b/.github/upload-preview.js @@ -1,4 +1,3 @@ -const fs = require('fs'); const path = require('path'); const { Octokit } = require('@octokit/rest'); const octokit = new Octokit({ auth: process.env.GH_PR_TOKEN }); @@ -7,11 +6,9 @@ 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 [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) { diff --git a/.github/workflows/add-new-issues-to-project.yml b/.github/workflows/add-new-issues-to-project.yml index fb7b6f2f3fc..cac1c9abdd7 100644 --- a/.github/workflows/add-new-issues-to-project.yml +++ b/.github/workflows/add-new-issues-to-project.yml @@ -1,16 +1,14 @@ 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@v0.3.0 + - uses: actions/add-to-project@v1.0.1 with: project-url: https://github.com/orgs/patternfly/projects/7 github-token: ${{ secrets.GH_PROJECTS }} diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 00000000000..c013ccb662f --- /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.js 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.js packages/react-docs/coverage diff --git a/.github/workflows/extensions.yml b/.github/workflows/extensions.yml index 3a436d5cf22..ef8ef00c74d 100644 --- a/.github/workflows/extensions.yml +++ b/.github/workflows/extensions.yml @@ -1,17 +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@v0.3.0 + - uses: actions/add-to-project@v1.0.1 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..e4fc55e74fb --- /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/public + + 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/public + + - name: Print environment variables + run: printenv + + - name: Run Cypress tests + run: yarn serve:integration & yarn test:integration -s $(node .github/split.js) + env: + WORKER_NUM: ${{ matrix.worker }} + WORKER_COUNT: 5 diff --git a/.github/workflows/promote.yml b/.github/workflows/promote.yml index 8386cc2a3ad..7d85ee4d25f 100644 --- a/.github/workflows/promote.yml +++ b/.github/workflows/promote.yml @@ -1,28 +1,27 @@ -name: promote +name: Promote on: workflow_dispatch: inputs: - core-version: - description: 'The PatternFly core version' + patternfly-version: + description: The version of PatternFly (`@patternfly/patternfly`) to promote to. required: false jobs: deploy: runs-on: ubuntu-latest - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - CORE_VERSION: ${{ github.event.inputs.core-version }} - RELEASE_VERSION: ${{ github.event.inputs.version }} - GH_TOKEN: ${{ secrets.GH_TOKEN_REDALLEN }} steps: - - uses: actions/checkout@v3 + - name: Check out project + uses: actions/checkout@v4 with: - token: ${{ secrets.GH_TOKEN_REDALLEN }} # needs to be an admin token to get around branch protection - - uses: actions/setup-node@v3 + # 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: - node-version: '18' - - name: Install deps - run: yarn install --frozen-lockfile - - name: Build dist - run: yarn build && yarn build:umd + 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 1926656e2b1..330ceaea326 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,11 @@ -### WARNING -- this file was generated by generate-workflows.js -name: release +name: Release on: push: branches: - v6 +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build: runs-on: ubuntu-latest @@ -309,47 +311,25 @@ jobs: WORKER_NUM: ${{ matrix.worker_num }} WORKER_COUNT: ${{ matrix.worker_count }} 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 - fetch-depth: '0' - - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - - uses: actions/setup-node@v1 + - name: Check out project + uses: actions/checkout@v4 with: - node-version: '18' - - uses: actions/cache@v2 - id: yarn-cache - name: Cache npm deps + # 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: | - 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/*/next - packages/*/deprecated - packages/*/components - packages/react-styles/css - packages/react-core/layouts - packages/react-core/helpers - 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 }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000000..f5642d8c9ad --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,18 @@ +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: 14 + exempt-issue-labels: accessibility,breaking change :boom:,security,pinned + stale-issue-label: wontfix + 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. + close-issue-message: 'This issue has been closed because it has not had activity since being marked as stale.' + close-pr-message: 'This PR has been closed because it has not had activity since being marked as stale.' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0b8205c972..470a424cfe6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -130,7 +130,7 @@ To make contributing components and packages easier a generator utility has been To start the generator run: -```bash +```sh yarn generate ``` @@ -179,9 +179,9 @@ Please ensure that all React UI components contributed meet the following guidel 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: +1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes: -```bash +```sh # Clone your fork of the repo into the current directory git clone https://github.com//patternfly-react.git # Navigate to the newly cloned directory @@ -192,15 +192,24 @@ git remote add upstream https://github.com/patternfly/patternfly-react.git git fetch upstream ``` -2. Create a branch: +2. Set up tooling -```text -$ git checkout -b my-branch upstream/main +[Install Node.js](https://nodejs.org/en/download/package-manager) version 20 (or higher). Then install the project dependencies and build it by running: + +```sh +yarn install +yarn build ``` -3. Generate your component +3. Create a branch: + +```sh +git checkout -b my-branch upstream/main +``` -```bash +4. Generate your component + +```sh # Run the tool to Generate the component scaffolding yarn generate ``` @@ -214,37 +223,37 @@ $ git checkout -b my-branch upstream/main ComponentName.md - Component Docs ``` -4. Develop your component. After development is complete, run build and ensure tests and lint standards pass. +5. Develop your component. After development is complete, run build and ensure tests and lint standards pass. -```text -$ yarn build -$ yarn test +```sh +yarn build +yarn test ``` Ensure no lint errors are introduced in `yarn-error.log` after running this command. ***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` -5. Add a commit using `git commit`: +6. 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 +7. Rebase 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). -```text -$ git fetch upstream -$ git rebase upstream/main +```sh +git fetch upstream +git rebase upstream/main ``` -7. Push +8. Push -```text -$ git push origin my-branch +```sh +git push origin my-branch ``` -8. Create a pull request +9. 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: diff --git a/README.md b/README.md index e5ae0c36ebb..26af484b27e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This project provides a set of React components for the [PatternFly project](htt 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). @@ -44,7 +44,7 @@ Before you begin, check out this [overview of PatternFly](http://patternfly.org/ #### Install a package manager Install a package manager before using the PatternFly libraries. -* [Use npm](https://nodejs.org/en/download) +* [Use npm](https://nodejs.org/en/download/package-manager) * [Use Yarn](https://yarnpkg.com/en/docs/getting-started) @@ -83,7 +83,6 @@ If you want to start with your existing project, skip to [Install and configure ### Contribution guidelines 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/jest.config.js b/jest.config.js index eac3fcc7b65..e72f794485d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -15,10 +15,10 @@ module.exports = { }, setupFilesAfterEnv: ['/packages/testSetup.ts'], testPathIgnorePatterns: ['/packages/react-integration/'], + transformIgnorePatterns: ['node_modules/victory-*/', '/node_modules/(?!(case-anything)/)'], coveragePathIgnorePatterns: ['/dist/'], moduleNameMapper: { '\\.(css|less)$': '/packages/react-styles/__mocks__/styleMock.js' }, - testEnvironment: 'jsdom', - transformIgnorePatterns: ['/node_modules/(?!(case-anything)/)'] + testEnvironment: 'jsdom' }; diff --git a/package.json b/package.json index 8e0d30c17d8..94c370fc6df 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "url": "https://github.com/patternfly/patternfly-react.git" }, "engines": { - "node": ">=18.0.0", + "node": ">=20", "yarn": ">=1.6.0" }, "keywords": [ @@ -29,10 +29,14 @@ "@babel/preset-react": "^7.24.1", "@babel/preset-typescript": "^7.24.1", "@octokit/rest": "^20.0.0", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-replace": "^5.0.5", + "@rollup/plugin-terser": "^0.4.4", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "14.5.2", - "@types/jest": "29.5.11", + "@types/jest": "29.5.12", "@types/react": "^18", "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^5.59.2", @@ -47,8 +51,8 @@ "fs-extra": "^11.1.1", "glob": "^9.3.0", "husky": "^4.3.0", - "jest": "27.2.5", - "jest-cli": "27.2.5", + "jest": "27.5.1", + "jest-cli": "27.5.1", "jest-transform-stub": "^2.0.0", "lerna": "^7.1.5", "lint-staged": "^14.0.0", @@ -57,10 +61,14 @@ "prettier": "^3.0.0", "react": "^18", "react-dom": "^18", + "rimraf": "^5.0.5", + "rollup": "^4.17.2", + "rollup-plugin-scss": "^4.0.0", + "sass": "^1.77.2", "surge": "^0.23.1", "ts-node": "^10.9.1", "ts-patch": "^2.1.0", - "typescript": "^4.7.4" + "typescript": "^5.4.5" }, "scripts": { "build": "yarn clean && yarn build:generate && yarn build:esm && yarn build:cjs && yarn build:subpaths && yarn build:single:packages", @@ -76,9 +84,9 @@ "clean:build": "rimraf .cache .eslintcache coverage", "clean:exports": "lerna run clean:exports --parallel --stream", "generate": "yarn plop", - "lint": "node --max-old-space-size=4096 node_modules/.bin/eslint --ext js,jsx,ts,tsx --cache", + "lint": "node --max-old-space-size=4096 node_modules/.bin/eslint --ext js,jsx,ts,tsx --cache --cache-strategy content", "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:md": "yarn eslint packages --ext md --no-eslintrc --config .eslintrc-md.json --cache --cache-strategy content", "lint:ts": "yarn lint packages/*/src", "lint:versions": "node scripts/verifyPatternflyVersions.js", "lint:tests": "yarn lint packages/*/src/components/*/__tests__/*.test.*", diff --git a/packages/eslint-plugin-patternfly-react/README.md b/packages/eslint-plugin-patternfly-react/README.md index f60a9ae6b58..347fa5ad0ed 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 ``` diff --git a/packages/eslint-plugin-patternfly-react/package.json b/packages/eslint-plugin-patternfly-react/package.json index db550e3ba9c..3620db8ff93 100644 --- a/packages/eslint-plugin-patternfly-react/package.json +++ b/packages/eslint-plugin-patternfly-react/package.json @@ -32,7 +32,6 @@ "eslint-plugin-import": "^2.13.0", "eslint-plugin-jest": "^27.0.0", "eslint-plugin-jsx-a11y": "^6.0.3", - "eslint-plugin-node": "^11.0.0", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-promise": "^6.0.0", "eslint-plugin-react": "^7.7.0", diff --git a/packages/react-charts/README.md b/packages/react-charts/README.md index f4afdae7292..b249e79b697 100644 --- a/packages/react-charts/README.md +++ b/packages/react-charts/README.md @@ -2,30 +2,15 @@ This package provides PatternFly charting components for [PatternFly][patternfly]. -### 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 -``` +```sh yarn add @patternfly/react-charts ``` or -``` +```sh npm install @patternfly/react-charts --save ``` diff --git a/packages/react-charts/package.json b/packages/react-charts/package.json index b7b7b2e474d..8169aecf6f9 100644 --- a/packages/react-charts/package.json +++ b/packages/react-charts/package.json @@ -33,24 +33,24 @@ "@patternfly/react-tokens": "^6.0.0-alpha.22", "hoist-non-react-statics": "^3.3.0", "lodash": "^4.17.21", - "tslib": "^2.5.0", - "victory-area": "^36.9.1", - "victory-axis": "^36.9.1", - "victory-bar": "^36.9.1", - "victory-box-plot": "^36.9.1", - "victory-chart": "^36.9.1", - "victory-core": "^36.9.1", - "victory-create-container": "^36.9.1", - "victory-cursor-container": "^36.9.1", - "victory-group": "^36.9.1", - "victory-legend": "^36.9.1", - "victory-line": "^36.9.1", - "victory-pie": "^36.9.1", - "victory-scatter": "^36.9.1", - "victory-stack": "^36.9.1", - "victory-tooltip": "^36.9.1", - "victory-voronoi-container": "^36.9.1", - "victory-zoom-container": "^36.9.1" + "tslib": "^2.6.2", + "victory-area": "^37.0.2", + "victory-axis": "^37.0.2", + "victory-bar": "^37.0.2", + "victory-box-plot": "^37.0.2", + "victory-chart": "^37.0.2", + "victory-core": "^37.0.2", + "victory-create-container": "^37.0.2", + "victory-cursor-container": "^37.0.2", + "victory-group": "^37.0.2", + "victory-legend": "^37.0.2", + "victory-line": "^37.0.2", + "victory-pie": "^37.0.2", + "victory-scatter": "^37.0.2", + "victory-stack": "^37.0.2", + "victory-tooltip": "^37.0.2", + "victory-voronoi-container": "^37.0.2", + "victory-zoom-container": "^37.0.2" }, "peerDependencies": { "react": "^17 || ^18", @@ -64,8 +64,6 @@ "@types/lodash": "^4.14.157", "css": "^2.2.3", "fs-extra": "^11.0.0", - "glob": "^7.1.2", - "rimraf": "^2.6.2", - "typescript": "^4.7.4" + "glob": "^7.1.2" } } diff --git a/packages/react-charts/src/components/Chart/Chart.tsx b/packages/react-charts/src/components/Chart/Chart.tsx index 4c5882dbad1..ef2067d083c 100644 --- a/packages/react-charts/src/components/Chart/Chart.tsx +++ b/packages/react-charts/src/components/Chart/Chart.tsx @@ -33,6 +33,7 @@ import { getChartTheme } from '../ChartUtils/chart-theme-types'; import { useEffect } from 'react'; 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, @@ -473,7 +474,7 @@ export const Chart: React.FunctionComponent = ({ children, colorScale, hasPatterns, - legendAllowWrap = false, + legendAllowWrap, legendComponent = , legendData, legendPosition = ChartCommonStyles.legend.position, @@ -526,7 +527,8 @@ export const Chart: React.FunctionComponent = ({ theme, ...containerComponent.props, className: getClassName({ className: containerComponent.props.className }), // Override VictoryContainer class name - ...(labelComponent && { labelComponent }) // Override label component props + ...(labelComponent && { labelComponent }), // Override label component props + ...(themeColor === ChartThemeColor.skeleton && { labelComponent: }) // Omit cursor and tooltips }); let legendXOffset = 0; @@ -539,6 +541,7 @@ export const Chart: React.FunctionComponent = ({ ...(name && { name: `${name}-${(legendComponent as any).type.displayName}` }), orientation: legendOrientation, theme, + themeColor, ...(legendDirection === 'rtl' && { dataComponent: legendComponent.props.dataComponent ? ( React.cloneElement(legendComponent.props.dataComponent, { transform: `translate(${legendXOffset})` }) @@ -597,6 +600,7 @@ export const Chart: React.FunctionComponent = ({ padding: defaultPadding, position: legendPosition, theme, + themeColor, width, ...(defaultPatternScale && { patternScale: defaultPatternScale }) }); @@ -615,6 +619,7 @@ export const Chart: React.FunctionComponent = ({ name: `${name}-${(child as any).type.displayName}-${index}` }), theme, + themeColor, ...childProps, ...((child as any).type.displayName === 'ChartPie' && { data: mergePatternData(childProps.data, defaultPatternScale) diff --git a/packages/react-charts/src/components/ChartAxis/ChartAxis.tsx b/packages/react-charts/src/components/ChartAxis/ChartAxis.tsx index 3949ea2cb35..b8ad8c9a1fd 100644 --- a/packages/react-charts/src/components/ChartAxis/ChartAxis.tsx +++ b/packages/react-charts/src/components/ChartAxis/ChartAxis.tsx @@ -18,7 +18,7 @@ import { VictoryAxis, VictoryAxisProps, VictoryAxisTTargetType } from 'victory-a import { ChartContainer } from '../ChartContainer/ChartContainer'; import { ChartLabel } from '../ChartLabel/ChartLabel'; import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; -import { getTheme } from '../ChartUtils/chart-theme'; +import { getComponentTheme, getTheme } from '../ChartUtils/chart-theme'; import { getAxisTheme } from '../ChartUtils/chart-theme-types'; /** @@ -451,6 +451,8 @@ export const ChartAxis: React.FunctionComponent = ({ theme = getTheme(themeColor), ...rest }: ChartAxisProps) => { + const componentTheme = getComponentTheme(themeColor); + // Clone so users can override container props const container = React.cloneElement(containerComponent, { theme, @@ -462,7 +464,8 @@ export const ChartAxis: React.FunctionComponent = ({ ...(name && { id: () => `${name}-${(axisLabelComponent as any).type.displayName}` }), - ...axisLabelComponent.props + ...axisLabelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); const getTickLabelComponent = () => @@ -470,7 +473,8 @@ export const ChartAxis: React.FunctionComponent = ({ ...(name && { id: (props: any) => `${name}-${(tickLabelComponent as any).type.displayName}-${props.index}` }), - ...tickLabelComponent.props + ...tickLabelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); // Note: containerComponent is required for theme diff --git a/packages/react-charts/src/components/ChartBullet/ChartBullet.tsx b/packages/react-charts/src/components/ChartBullet/ChartBullet.tsx index 42ab60edcd5..ca5cc77c9e4 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBullet.tsx +++ b/packages/react-charts/src/components/ChartBullet/ChartBullet.tsx @@ -594,6 +594,7 @@ export const ChartBullet: React.FunctionComponent = ({ standalone: false, subTitle: groupSubTitle, title: groupTitle, + themeColor, width, ...groupTitleComponent.props }); @@ -608,6 +609,7 @@ export const ChartBullet: React.FunctionComponent = ({ standalone: false, subTitle, theme, + themeColor, title, titlePosition, width, @@ -617,7 +619,12 @@ export const ChartBullet: React.FunctionComponent = ({ // Comparative error measure const comparativeErrorMeasure = React.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, @@ -627,6 +634,7 @@ export const ChartBullet: React.FunctionComponent = ({ labels, padding, standalone: false, + themeColor, width: chartSize.width, y: comparativeErrorMeasureDataY, ...comparativeErrorMeasureComponent.props @@ -635,7 +643,12 @@ export const ChartBullet: React.FunctionComponent = ({ // Comparative warning measure const comparativeWarningMeasure = React.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, @@ -645,6 +658,7 @@ export const ChartBullet: React.FunctionComponent = ({ labels, padding, standalone: false, + themeColor, width: chartSize.width, y: comparativeWarningMeasureDataY, ...comparativeWarningMeasureComponent.props @@ -652,13 +666,14 @@ export const ChartBullet: React.FunctionComponent = ({ // Comparative zero measure const comparativeZeroMeasure = React.cloneElement(comparativeZeroMeasureComponent, { - barWidth: getComparativeMeasureWidth({ height: chartSize.height, horizontal, width: chartSize.width }), + 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 }); @@ -691,6 +706,7 @@ export const ChartBullet: React.FunctionComponent = ({ orientation: legendOrientation, position: legendPosition, theme, + themeColor, ...(legendDirection === 'rtl' && { dataComponent: legendComponent.props.dataComponent ? ( React.cloneElement(legendComponent.props.dataComponent, { transform: `translate(${legendXOffset})` }) @@ -700,7 +716,10 @@ export const ChartBullet: React.FunctionComponent = ({ }), ...(legendDirection === 'rtl' && { labelComponent: legendComponent.props.labelComponent ? ( - React.cloneElement(legendComponent.props.labelComponent, { direction: 'rtl', dx: legendXOffset - 30 }) + React.cloneElement(legendComponent.props.labelComponent, { + direction: 'rtl', + dx: legendXOffset - 30 + }) ) : ( ) @@ -720,7 +739,7 @@ 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, width: chartSize.width, @@ -732,7 +751,12 @@ export const ChartBullet: React.FunctionComponent = ({ const primarySegmentedMeasure = React.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, @@ -752,7 +776,7 @@ export const ChartBullet: React.FunctionComponent = ({ const qualitativeRange = React.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, @@ -762,6 +786,7 @@ export const ChartBullet: React.FunctionComponent = ({ labels, padding, standalone: false, + themeColor, width: chartSize.width, y: qualitativeRangeDataY, y0: qualitativeRangeDataY0, @@ -868,6 +893,7 @@ export const ChartBullet: React.FunctionComponent = ({ 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, diff --git a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx b/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx index 9fb745700e0..9e90749308b 100644 --- a/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx +++ b/packages/react-charts/src/components/ChartBullet/ChartBulletComparativeErrorMeasure.tsx @@ -201,6 +201,7 @@ export const ChartBulletComparativeErrorMeasure: React.FunctionComponent { + const componentTheme = getComponentTheme(themeColor); const titleProps = titleComponent ? titleComponent.props : {}; const showBoth = title && subTitle; return React.cloneElement(titleComponent, { @@ -183,7 +185,8 @@ export const ChartBulletGroupTitle: React.FunctionComponent = // Returns title const getTitle = () => { + const componentTheme = getComponentTheme(themeColor); const showBoth = title && subTitle; let labelPosition: 'bottom' | 'left' | 'top-left' = horizontal ? 'left' : 'bottom'; @@ -215,7 +217,8 @@ export const ChartBulletTitle: React.FunctionComponent = dy, labelPosition }), - ...titleComponent.props + ...titleComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); }; diff --git a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-theme.ts b/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-theme.ts index 3550f57b8e2..2cfb13f9950 100644 --- a/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-theme.ts +++ b/packages/react-charts/src/components/ChartBullet/utils/chart-bullet-theme.ts @@ -7,6 +7,8 @@ import { } from './chart-bullet-data'; 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[]; @@ -134,5 +136,8 @@ export const getBulletThemeWithLegendColorScale = ({ 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/components/ChartCursorContainer/ChartCursorContainer.tsx b/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.tsx index a5790a3523c..19ce90ca2a9 100644 --- a/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.tsx +++ b/packages/react-charts/src/components/ChartCursorContainer/ChartCursorContainer.tsx @@ -11,7 +11,7 @@ import { } from 'victory-cursor-container'; import { ChartLabel } from '../ChartLabel/ChartLabel'; import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; -import { getTheme } from '../ChartUtils/chart-theme'; +import { getComponentTheme, getTheme } from '../ChartUtils/chart-theme'; import { getClassName } from '../ChartUtils/chart-helpers'; /** @@ -210,10 +210,12 @@ export const ChartCursorContainer: React.FunctionComponent, // Note that Victory provides its own label component here ...rest }: ChartCursorContainerProps) => { + const componentTheme = getComponentTheme(themeColor); const chartClassName = getClassName({ className }); const chartCursorLabelComponent = React.cloneElement(cursorLabelComponent, { theme, - ...cursorLabelComponent.props + ...cursorLabelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); // Clone so users can override cursor container props diff --git a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.tsx b/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.tsx index 5d16764429c..83e600ad0a5 100644 --- a/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.tsx +++ b/packages/react-charts/src/components/ChartCursorTooltip/ChartCursorTooltip.tsx @@ -287,9 +287,9 @@ 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, { pointerLength: _pointerLength, 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 index 89225293033..47cb5ac054a 100644 --- a/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorFlyout.test.tsx.snap +++ b/packages/react-charts/src/components/ChartCursorTooltip/__snapshots__/ChartCursorFlyout.test.tsx.snap @@ -18,12 +18,12 @@ exports[`allows tooltip via container component 1`] = ` width="200" > = ({ 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), @@ -603,13 +606,13 @@ 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 chartInnerRadius = innerRadius ? Helpers.evaluateProp(innerRadius, undefined) : chartRadius - 9; // Todo: Add pf-core variable const centerSubTitle = subTitle && subTitlePosition === 'center'; // Returns title and subtitle @@ -659,7 +662,8 @@ export const ChartDonut: React.FunctionComponent = ({ padding: defaultPadding, width }), - ...subTitleProps + ...subTitleProps, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); }; @@ -692,7 +696,8 @@ export const ChartDonut: React.FunctionComponent = ({ padding: defaultPadding, width }), - ...titleProps + ...titleProps, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); }; @@ -710,6 +715,7 @@ export const ChartDonut: React.FunctionComponent = ({ radius={chartRadius > 0 ? chartRadius : 0} standalone={false} theme={theme} + themeColor={themeColor} width={width} {...rest} /> diff --git a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.tsx b/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.tsx index 6cb8d23df09..0f890ca31c6 100644 --- a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.tsx +++ b/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutThreshold.tsx @@ -462,7 +462,7 @@ export const ChartDonutThreshold: React.FunctionComponent diff --git a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.tsx b/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.tsx index 90b8cf1ee03..cbd540dc94b 100644 --- a/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.tsx +++ b/packages/react-charts/src/components/ChartDonutUtilization/ChartDonutUtilization.tsx @@ -688,6 +688,7 @@ export const ChartDonutUtilization: React.FunctionComponent diff --git a/packages/react-charts/src/components/ChartGroup/ChartGroup.tsx b/packages/react-charts/src/components/ChartGroup/ChartGroup.tsx index 85200ec38d0..6bb01abb496 100644 --- a/packages/react-charts/src/components/ChartGroup/ChartGroup.tsx +++ b/packages/react-charts/src/components/ChartGroup/ChartGroup.tsx @@ -499,7 +499,8 @@ export const ChartGroup: React.FunctionComponent = ({ {renderChildrenWithPatterns({ children, - patternScale: defaultPatternScale + patternScale: defaultPatternScale, + themeColor })} {isPatternDefs && getPatternDefs({ patternId, colorScale: defaultColorScale })} diff --git a/packages/react-charts/src/components/ChartLegend/ChartLegend.tsx b/packages/react-charts/src/components/ChartLegend/ChartLegend.tsx index 1f4dae53015..c2af1359289 100644 --- a/packages/react-charts/src/components/ChartLegend/ChartLegend.tsx +++ b/packages/react-charts/src/components/ChartLegend/ChartLegend.tsx @@ -21,7 +21,7 @@ import { ChartContainer } from '../ChartContainer/ChartContainer'; import { ChartLabel } from '../ChartLabel/ChartLabel'; import { ChartPoint } from '../ChartPoint/ChartPoint'; import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; -import { getTheme } from '../ChartUtils/chart-theme'; +import { getComponentTheme, getTheme } from '../ChartUtils/chart-theme'; /** * ChartLegend renders a chart legend component. @@ -317,6 +317,8 @@ export const ChartLegend: React.FunctionComponent = ({ theme = getTheme(themeColor), ...rest }: ChartLegendProps) => { + const componentTheme = getComponentTheme(themeColor); + // Merge pattern IDs with `style.data.fill` property const getDefaultStyle = () => { if (!patternScale) { @@ -350,14 +352,16 @@ export const ChartLegend: React.FunctionComponent = ({ const getLabelComponent = () => React.cloneElement(labelComponent, { ...(name && { id: (props: any) => `${name}-${(labelComponent as any).type.displayName}-${props.index}` }), - ...labelComponent.props + ...labelComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); const getTitleComponent = () => React.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 + ...titleComponent.props, + ...(componentTheme?.label && componentTheme.label) // override backgroundStyle }); // Note: containerComponent is required for theme diff --git a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.tsx b/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.tsx index 3599291d927..167a7e4244a 100644 --- a/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.tsx +++ b/packages/react-charts/src/components/ChartLegendTooltip/ChartLegendTooltip.tsx @@ -346,7 +346,7 @@ export const ChartLegendTooltip: React.FunctionComponent { - 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( @@ -401,6 +401,7 @@ export const ChartLegendTooltip: React.FunctionComponent { - 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, @@ -230,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) { @@ -246,7 +246,7 @@ export const ChartLegendTooltipContent: React.FunctionComponent height - _flyoutHeight / 2) { @@ -290,8 +290,8 @@ export const ChartLegendTooltipContent: React.FunctionComponent { - const _x = x + Helpers.evaluateProp(dx); + const _x = x + (Helpers.evaluateProp(dx, undefined) as number); return React.cloneElement(valueLabelComponent, { style: getStyle(style), diff --git a/packages/react-charts/src/components/ChartPie/ChartPie.tsx b/packages/react-charts/src/components/ChartPie/ChartPie.tsx index 61263aeecc8..194e0b00730 100644 --- a/packages/react-charts/src/components/ChartPie/ChartPie.tsx +++ b/packages/react-charts/src/components/ChartPie/ChartPie.tsx @@ -593,6 +593,7 @@ export const ChartPie: React.FunctionComponent = ({ key: 'pf-chart-pie-legend', orientation: legendOrientation, theme, + themeColor, ...(legendDirection === 'rtl' && { dataComponent: legendComponent.props.dataComponent ? ( React.cloneElement(legendComponent.props.dataComponent, { transform: `translate(${legendXOffset})` }) diff --git a/packages/react-charts/src/components/ChartPoint/ChartPoint.tsx b/packages/react-charts/src/components/ChartPoint/ChartPoint.tsx index 14f6010b8c3..8768f990c66 100644 --- a/packages/react-charts/src/components/ChartPoint/ChartPoint.tsx +++ b/packages/react-charts/src/components/ChartPoint/ChartPoint.tsx @@ -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); }; diff --git a/packages/react-charts/src/components/ChartTheme/ChartTheme.ts b/packages/react-charts/src/components/ChartTheme/ChartTheme.ts index fcd2b214015..ad61b6d420f 100644 --- a/packages/react-charts/src/components/ChartTheme/ChartTheme.ts +++ b/packages/react-charts/src/components/ChartTheme/ChartTheme.ts @@ -1,6 +1,44 @@ import { VictoryThemeDefinition } from 'victory-core'; -// Note: Victory incorrectly typed ThemeBaseProps.padding as number instead of PaddingProps +/** + * Chart component theme definition + * @private + * @beta + */ +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 {} /** @@ -8,3 +46,10 @@ export interface ChartThemeDefinitionInterface extends VictoryThemeDefinition {} * @public */ export type ChartThemeDefinition = ChartThemeDefinitionInterface; + +/** + * Chart component theme definition + * @private + * @beta + */ +export type ChartComponentThemeDefinition = ChartComponentThemeDefinitionInterface; diff --git a/packages/react-charts/src/components/ChartTheme/ChartThemeColor.ts b/packages/react-charts/src/components/ChartTheme/ChartThemeColor.ts index 176c4e067e3..e501941a174 100644 --- a/packages/react-charts/src/components/ChartTheme/ChartThemeColor.ts +++ b/packages/react-charts/src/components/ChartTheme/ChartThemeColor.ts @@ -10,6 +10,7 @@ interface ChartThemeColorInterface { multiUnordered: string; orange: string; purple: string; + skeleton: string; } /** @@ -49,5 +50,6 @@ export const ChartThemeColor: ChartThemeColorInterface = { multiOrdered: 'multi-ordered', multiUnordered: 'multi-unordered', orange: 'orange', - purple: 'purple' + purple: 'purple', + skeleton: 'skeleton' }; diff --git a/packages/react-charts/src/components/ChartTheme/ChartThemeTypes.ts b/packages/react-charts/src/components/ChartTheme/ChartThemeTypes.ts index e2cf585e630..0ce2ec9a558 100644 --- a/packages/react-charts/src/components/ChartTheme/ChartThemeTypes.ts +++ b/packages/react-charts/src/components/ChartTheme/ChartThemeTypes.ts @@ -1,6 +1,6 @@ -import { ChartThemeDefinition } from './ChartTheme'; +import { ChartComponentThemeDefinition, ChartThemeDefinition } from './ChartTheme'; import { AxisTheme } from './themes/components/axis-theme'; -import { BaseTheme } from './themes/base-theme'; +import { BaseComponentTheme, BaseTheme } from './themes/base-theme'; import { BulletTheme, BulletComparativeErrorMeasureTheme, @@ -20,6 +20,7 @@ import { ThresholdTheme } from './themes/components/threshold-theme'; /** * Axis theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartAxisTheme: ChartThemeDefinition = AxisTheme; @@ -29,92 +30,114 @@ export const ChartAxisTheme: ChartThemeDefinition = AxisTheme; */ export const ChartBaseTheme: ChartThemeDefinition = BaseTheme; +/** + * Base component theme + * @private + * @beta + */ +export const ChartBaseComponentTheme: ChartComponentThemeDefinition = BaseComponentTheme; + /** * Bullet comparative error measure theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletComparativeErrorMeasureTheme: ChartThemeDefinition = BulletComparativeErrorMeasureTheme; /** * Bullet comparative measure theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletComparativeMeasureTheme: ChartThemeDefinition = BulletComparativeMeasureTheme; /** * Bullet comparative measure warning theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletComparativeWarningMeasureTheme: ChartThemeDefinition = BulletComparativeWarningMeasureTheme; /** * Bullet group title theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletGroupTitleTheme: ChartThemeDefinition = BulletGroupTitleTheme; /** * Bullet primary dot measure theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletPrimaryDotMeasureTheme: ChartThemeDefinition = BulletPrimaryDotMeasureTheme; /** * Bullet primary negative measure theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletPrimaryNegativeMeasureTheme: ChartThemeDefinition = BulletPrimaryNegativeMeasureTheme; /** * Bullet primary segmented measure theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletPrimarySegmentedMeasureTheme: ChartThemeDefinition = BulletPrimarySegmentedMeasureTheme; /** * Bullet qualitative range theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletQualitativeRangeTheme: ChartThemeDefinition = BulletQualitativeRangeTheme; /** * Bullet theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartBulletTheme: ChartThemeDefinition = BulletTheme; /** * Donut utilization dynamic theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartDonutUtilizationDynamicTheme: ChartThemeDefinition = DonutUtilizationDynamicTheme; /** * Donut utilization static theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartDonutUtilizationStaticTheme: ChartThemeDefinition = DonutUtilizationStaticTheme; /** * Donut theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartDonutTheme: ChartThemeDefinition = DonutTheme; /** * Donut threshold dynamic theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartDonutThresholdDynamicTheme: ChartThemeDefinition = DonutThresholdDynamicTheme; /** - * ChartDonutThresholdStatic theme + * Donut threshold static theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartDonutThresholdStaticTheme: ChartThemeDefinition = DonutThresholdStaticTheme; /** - * Donut threshold static theme + * Threshold static theme * @private + * @deprecated See ChartBaseComponentTheme */ export const ChartThresholdTheme: ChartThemeDefinition = ThresholdTheme; diff --git a/packages/react-charts/src/components/ChartTheme/themes/base-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/base-theme.ts index dd5233d0188..03f1615522f 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/base-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/base-theme.ts @@ -96,6 +96,29 @@ import chart_voronoi_flyout_stroke_Width from '@patternfly/react-tokens/dist/esm 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_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_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 @@ -116,6 +139,7 @@ const LABEL_PROPS = { 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 @@ -133,10 +157,10 @@ const STROKE_LINE_CAP = chart_global_stroke_line_cap.value; const STROKE_LINE_JOIN = chart_global_stroke_line_join.value; /** - * Victory theme properties only + * Base theme containing Victory properties only * @private */ -export const BaseTheme = { +export const BaseTheme: ChartThemeDefinition = { area: { ...LAYOUT_PROPS, style: { @@ -167,7 +191,7 @@ export const BaseTheme = { }, grid: { fill: chart_axis_grid_Fill.var, - stroke: 'none', + stroke: 'transparent', pointerEvents: chart_axis_grid_PointerEvents.value, strokeLinecap: STROKE_LINE_CAP, strokeLinejoin: STROKE_LINE_JOIN @@ -198,7 +222,7 @@ export const BaseTheme = { }, labels: LABEL_PROPS } - }, + } as any, // Victory is missing barWidth boxplot: { ...LAYOUT_PROPS, style: { @@ -329,7 +353,7 @@ export const BaseTheme = { 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, @@ -346,7 +370,7 @@ export const BaseTheme = { fill: chart_tooltip_Fill.var, // text pointerEvents: chart_tooltip_PointerEvents.var } - }, + } as any, // Victory is missing cornerRadius and pointerWidth voronoi: { ...LAYOUT_PROPS, style: { @@ -371,3 +395,127 @@ export const BaseTheme = { } } }; + +/** + * Base component theme + * @private + * @beta + */ +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 + } + }, + bulletPrimaryNegativeMeasure: { + group: { + height: chart_bullet_Height.value + } + }, + bulletPrimarySegmentedMeasure: { + group: { + height: chart_bullet_Height.value + } + }, + 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 + } 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 + } + }, + 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 + } 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 + } 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/components/ChartTheme/themes/color-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/color-theme.ts index 46c9dff6264..fda4be8b3c2 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/color-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/color-theme.ts @@ -1,12 +1,39 @@ +/* eslint-disable camelcase */ +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 theme properties only + * Victory color theme * @private */ -export const ColorTheme = (props: ColorThemeInterface) => { +export const ColorTheme = (props: ColorThemeInterface): ChartThemeDefinition => { const { COLOR_SCALE } = props; return { @@ -77,3 +104,146 @@ export const ColorTheme = (props: ColorThemeInterface) => { } }; }; + +/** + * Component color theme + * @private + * @beta + */ +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/components/ChartTheme/themes/colors/blue-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/blue-theme.ts index 5263fc4b02d..7f5d45e8f78 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/blue-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/blue-theme.ts @@ -4,7 +4,7 @@ import chart_theme_blue_ColorScale_200 from '@patternfly/react-tokens/dist/esm/c 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 { ColorTheme, ColorComponentTheme } from '../color-theme'; // Color scale // See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit @@ -23,3 +23,12 @@ const COLOR_SCALE = [ export const BlueColorTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Blue color component theme + * @private + * @beta + */ +export const BlueColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/cyan-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/cyan-theme.ts index d08e05c7112..cd3fadde53e 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/cyan-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/cyan-theme.ts @@ -4,7 +4,7 @@ import chart_theme_cyan_ColorScale_200 from '@patternfly/react-tokens/dist/esm/c import chart_theme_cyan_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_cyan_ColorScale_300'; import chart_theme_cyan_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_cyan_ColorScale_400'; import chart_theme_cyan_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_cyan_ColorScale_500'; -import { ColorTheme } from '../color-theme'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; // Color scale // See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit @@ -23,3 +23,12 @@ const COLOR_SCALE = [ export const CyanColorTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Cyan color component theme + * @private + * @beta + */ +export const CyanColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/gold-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/gold-theme.ts index 86e87745a95..64ff8b833c9 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/gold-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/gold-theme.ts @@ -4,7 +4,7 @@ import chart_theme_gold_ColorScale_200 from '@patternfly/react-tokens/dist/esm/c import chart_theme_gold_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_gold_ColorScale_300'; import chart_theme_gold_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_gold_ColorScale_400'; import chart_theme_gold_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_gold_ColorScale_500'; -import { ColorTheme } from '../color-theme'; +import { ColorTheme, ColorComponentTheme } from '../color-theme'; // Color scale // See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit @@ -23,3 +23,12 @@ const COLOR_SCALE = [ export const GoldColorTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Gold color component theme + * @private + * @beta + */ +export const GoldColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/gray-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/gray-theme.ts index ffe32a26632..b84cb9d9a49 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/gray-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/gray-theme.ts @@ -4,7 +4,7 @@ import chart_theme_gray_ColorScale_200 from '@patternfly/react-tokens/dist/esm/c 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 { ColorTheme, ColorComponentTheme } from '../color-theme'; // Color scale // See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit @@ -23,3 +23,12 @@ const COLOR_SCALE = [ export const GrayColorTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Gray component theme + * @private + * @beta + */ +export const GrayColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/green-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/green-theme.ts index 1220467981e..21fe9d393c2 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/green-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/green-theme.ts @@ -4,7 +4,7 @@ import chart_theme_green_ColorScale_200 from '@patternfly/react-tokens/dist/esm/ 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 { ColorTheme, ColorComponentTheme } from '../color-theme'; // Color scale // See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit @@ -23,3 +23,12 @@ const COLOR_SCALE = [ export const GreenColorTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Green color component theme + * @private + * @beta + */ +export const GreenColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/multi-ordered-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/multi-ordered-theme.ts index 2ce1ad1e5ab..dc383575975 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/multi-ordered-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/multi-ordered-theme.ts @@ -24,7 +24,7 @@ import chart_theme_multi_color_ordered_ColorScale_2200 from '@patternfly/react-t 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 { 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 @@ -63,3 +63,12 @@ const COLOR_SCALE = [ export const MultiColorOrderedTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Multi-color ordered component theme + * @private + * @beta + */ +export const MultiColorOrderedComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/multi-unordered-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/multi-unordered-theme.ts index eeff0952a38..dd524d32ab4 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/multi-unordered-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/multi-unordered-theme.ts @@ -34,7 +34,7 @@ import chart_theme_multi_color_unordered_ColorScale_3200 from '@patternfly/react 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 { 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 @@ -83,3 +83,12 @@ const COLOR_SCALE = [ export const MultiColorUnorderedTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Multi-color unordered component theme + * @private + * @beta + */ +export const MultiColorUnorderedComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/orange-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/orange-theme.ts index ca81d6608db..cb29dcbba91 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/orange-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/orange-theme.ts @@ -4,7 +4,7 @@ import chart_theme_orange_ColorScale_200 from '@patternfly/react-tokens/dist/esm 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 { ColorTheme, ColorComponentTheme } from '../color-theme'; // Color scale // See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit @@ -23,3 +23,12 @@ const COLOR_SCALE = [ export const OrangeColorTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Orange color component theme + * @private + * @beta + */ +export const OrangeColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/purple-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/purple-theme.ts index 1982c9c6c51..21ffef53f35 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/colors/purple-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/purple-theme.ts @@ -4,7 +4,7 @@ import chart_theme_purple_ColorScale_200 from '@patternfly/react-tokens/dist/esm 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 { ColorTheme, ColorComponentTheme } from '../color-theme'; // Color scale // See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit @@ -23,3 +23,12 @@ const COLOR_SCALE = [ export const PurpleColorTheme = ColorTheme({ COLOR_SCALE }); + +/** + * Purple color component theme + * @private + * @beta + */ +export const PurpleColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/colors/skeleton-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/colors/skeleton-theme.ts new file mode 100644 index 00000000000..9b58ce91fbf --- /dev/null +++ b/packages/react-charts/src/components/ChartTheme/themes/colors/skeleton-theme.ts @@ -0,0 +1,35 @@ +/* eslint-disable camelcase */ +import { ColorTheme, ColorComponentTheme } from '../skeleton-theme'; +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'; + +// Color scale +// See https://docs.google.com/document/d/1cw10pJFXWruB1SA8TQwituxn5Ss6KpxYPCOYGrH8qAY/edit +const COLOR_SCALE = [ + 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 +]; + +/** + * Skeleton color theme + * @private + * @beta + */ +export const SkeletonColorTheme = ColorTheme({ + COLOR_SCALE +}); + +/** + * Skeleton color theme + * @private + * @beta + */ +export const SkeletonColorComponentTheme = ColorComponentTheme({ + COLOR_SCALE +}); diff --git a/packages/react-charts/src/components/ChartTheme/themes/components/axis-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/components/axis-theme.ts index 4e34d1d1273..73ae707e5db 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/components/axis-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/components/axis-theme.ts @@ -5,6 +5,7 @@ import chart_axis_tick_stroke_Color from '@patternfly/react-tokens/dist/esm/char /** * Axis theme * @private + * @deprecated See BaseComponentTheme */ export const AxisTheme = { axis: { diff --git a/packages/react-charts/src/components/ChartTheme/themes/components/bullet-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/components/bullet-theme.ts index ec4b73c59eb..fe27d15fda4 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/components/bullet-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/components/bullet-theme.ts @@ -30,6 +30,7 @@ import chart_global_layout_Padding from '@patternfly/react-tokens/dist/esm/chart /** * Bullet theme * @private + * @deprecated See BaseComponentTheme */ export const BulletTheme = { chart: { @@ -40,6 +41,7 @@ export const BulletTheme = { /** * Bullet comparative error measure theme * @private + * @deprecated See BaseComponentTheme */ export const BulletComparativeErrorMeasureTheme = { bar: { @@ -57,6 +59,7 @@ export const BulletComparativeErrorMeasureTheme = { /** * Bullet comparative measure theme * @private + * @deprecated See BaseComponentTheme */ export const BulletComparativeMeasureTheme = { bar: { @@ -74,6 +77,7 @@ export const BulletComparativeMeasureTheme = { /** * Bullet comparative measure warning theme * @private + * @deprecated See BaseComponentTheme */ export const BulletComparativeWarningMeasureTheme = { bar: { @@ -91,6 +95,7 @@ export const BulletComparativeWarningMeasureTheme = { /** * Bullet group title theme * @private + * @deprecated See BaseComponentTheme */ export const BulletGroupTitleTheme = { chart: { @@ -115,6 +120,7 @@ export const BulletGroupTitleTheme = { /** * Bullet primary dot measure theme * @private + * @deprecated See BaseComponentTheme */ export const BulletPrimaryDotMeasureTheme = { group: { @@ -125,6 +131,7 @@ export const BulletPrimaryDotMeasureTheme = { /** * Bullet primary negative measure theme * @private + * @deprecated See BaseComponentTheme */ export const BulletPrimaryNegativeMeasureTheme = { group: { @@ -142,6 +149,7 @@ export const BulletPrimaryNegativeMeasureTheme = { /** * Bullet primary segmented measure theme * @private + * @deprecated See BaseComponentTheme */ export const BulletPrimarySegmentedMeasureTheme = { group: { @@ -152,6 +160,7 @@ export const BulletPrimarySegmentedMeasureTheme = { /** * Bullet qualitative range theme * @private + * @deprecated See BaseComponentTheme */ export const BulletQualitativeRangeTheme = { group: { diff --git a/packages/react-charts/src/components/ChartTheme/themes/components/donut-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/components/donut-theme.ts index 50409084ee4..e2182a0de8c 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/components/donut-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/components/donut-theme.ts @@ -7,6 +7,7 @@ import chart_donut_pie_Width from '@patternfly/react-tokens/dist/esm/chart_donut /** * Donut theme * @private + * @deprecated See BaseComponentTheme */ export const DonutTheme = { pie: { diff --git a/packages/react-charts/src/components/ChartTheme/themes/components/donut-threshold-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/components/donut-threshold-theme.ts index 35ff8458818..3ad71154a24 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/components/donut-threshold-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/components/donut-threshold-theme.ts @@ -13,6 +13,7 @@ import chart_donut_threshold_static_pie_Width from '@patternfly/react-tokens/dis /** * Donut threshold dynamic theme * @private + * @deprecated See BaseComponentTheme */ export const DonutThresholdDynamicTheme = { legend: { @@ -28,6 +29,7 @@ export const DonutThresholdDynamicTheme = { /** * Donut threshold static theme * @private + * @deprecated See BaseComponentTheme */ export const DonutThresholdStaticTheme = { pie: { diff --git a/packages/react-charts/src/components/ChartTheme/themes/components/donut-utilization-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/components/donut-utilization-theme.ts index c8f5dd2208c..48cc0f67894 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/components/donut-utilization-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/components/donut-utilization-theme.ts @@ -11,6 +11,7 @@ import chart_donut_utilization_static_pie_Padding from '@patternfly/react-tokens /** * Donut utilization dynamic theme * @private + * @deprecated See BaseComponentTheme */ export const DonutUtilizationDynamicTheme = { pie: { @@ -24,6 +25,7 @@ export const DonutUtilizationDynamicTheme = { /** * Donut utilization static theme * @private + * @deprecated See BaseComponentTheme */ export const DonutUtilizationStaticTheme = { legend: { diff --git a/packages/react-charts/src/components/ChartTheme/themes/components/threshold-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/components/threshold-theme.ts index ac16660a0d6..ef43eae8442 100644 --- a/packages/react-charts/src/components/ChartTheme/themes/components/threshold-theme.ts +++ b/packages/react-charts/src/components/ChartTheme/themes/components/threshold-theme.ts @@ -5,6 +5,7 @@ import chart_threshold_stroke_Width from '@patternfly/react-tokens/dist/esm/char /** * Threshold theme * @private + * @deprecated See BaseComponentTheme */ export const ThresholdTheme = { line: { diff --git a/packages/react-charts/src/components/ChartTheme/themes/skeleton-theme.ts b/packages/react-charts/src/components/ChartTheme/themes/skeleton-theme.ts new file mode 100644 index 00000000000..21863aed04f --- /dev/null +++ b/packages/react-charts/src/components/ChartTheme/themes/skeleton-theme.ts @@ -0,0 +1,307 @@ +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 + */ +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 + } + } + }, + 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 + * @beta + */ +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/components/ChartThreshold/ChartThreshold.tsx b/packages/react-charts/src/components/ChartThreshold/ChartThreshold.tsx index 971cdc6af11..9d6566d8a3d 100644 --- a/packages/react-charts/src/components/ChartThreshold/ChartThreshold.tsx +++ b/packages/react-charts/src/components/ChartThreshold/ChartThreshold.tsx @@ -456,7 +456,7 @@ export const ChartThreshold: React.FunctionComponent = ({ strokeWidth: getStrokeWidth() }; } - return ; + return ; }; ChartThreshold.displayName = 'ChartThreshold'; diff --git a/packages/react-charts/src/components/ChartThreshold/examples/ChartThreshold.md b/packages/react-charts/src/components/ChartThreshold/examples/ChartThreshold.md index 128ee54a7c5..efe5fb1a30a 100644 --- a/packages/react-charts/src/components/ChartThreshold/examples/ChartThreshold.md +++ b/packages/react-charts/src/components/ChartThreshold/examples/ChartThreshold.md @@ -116,6 +116,7 @@ class MultiColorChart extends React.Component { top: 50 }} maxDomain={{ y: 9 }} + name="chart1" themeColor={ChartThemeColor.multiUnordered} width={width} > 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 index 78297539c7b..89225293033 100644 --- a/packages/react-charts/src/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap +++ b/packages/react-charts/src/components/ChartTooltip/__snapshots__/ChartTooltip.test.tsx.snap @@ -18,12 +18,12 @@ exports[`allows tooltip via container component 1`] = ` width="200" > ``` +### Fixed tooltip +This demonstrates how to adjust the tooltip position and label radius +```js +import React from 'react'; +import { ChartDonut, ChartTooltip } from '@patternfly/react-charts'; + +
+ } + labelRadius={46} + labels={({ datum }) => `${datum.x}: ${datum.y}%`} + name="chart5" + subTitle="Pets" + title="100" + themeColor={ChartThemeColor.cyan} + width={150} + /> +
+``` + ### Legend -This demonstrates an approach for applying tooltips to a legend using a custom label component. +This demonstrates an approach for applying tooltips to a legend using a custom legend label component. ```js import React from 'react'; diff --git a/packages/react-charts/src/components/ChartUtils/chart-legend.ts b/packages/react-charts/src/components/ChartUtils/chart-legend.ts index 3bbd51bda43..d2e07752e95 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-legend.ts +++ b/packages/react-charts/src/components/ChartUtils/chart-legend.ts @@ -21,6 +21,7 @@ interface ChartLegendInterface { 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 } @@ -82,6 +83,7 @@ export const getComputedLegend = ({ patternScale, position = ChartCommonStyles.legend.position, theme, + themeColor, width, // destructure last @@ -142,6 +144,7 @@ export const getComputedLegend = ({ patternScale, standalone: false, theme, + themeColor, x: legendX > 0 ? legendX : 0, y: legendY > 0 ? legendY : 0 }); diff --git a/packages/react-charts/src/components/ChartUtils/chart-patterns.tsx b/packages/react-charts/src/components/ChartUtils/chart-patterns.tsx index 08944b00b1c..4eb229483b1 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-patterns.tsx +++ b/packages/react-charts/src/components/ChartUtils/chart-patterns.tsx @@ -10,6 +10,7 @@ interface PatternPropsInterface { patternId?: string; patternScale?: string[]; patternUnshiftIndex?: number; + themeColor?: string; themeColorScale?: string[]; } @@ -359,7 +360,7 @@ export const useDefaultPatternProps = ({ * Helper function to render children with patterns * @private */ -export const renderChildrenWithPatterns = ({ children, patternScale }: PatternPropsInterface) => +export const renderChildrenWithPatterns = ({ children, patternScale, themeColor }: PatternPropsInterface) => React.Children.toArray(children).map((child, index) => { if (React.isValidElement(child)) { const { ...childProps } = child.props; @@ -375,6 +376,7 @@ export const renderChildrenWithPatterns = ({ children, patternScale }: PatternPr } const _child = React.cloneElement(child, { ...(patternScale && { patternScale }), + ...(themeColor && { themeColor }), ...childProps, style // Override child props }); diff --git a/packages/react-charts/src/components/ChartUtils/chart-theme-types.ts b/packages/react-charts/src/components/ChartUtils/chart-theme-types.ts index baeab5caae6..17fbae280b3 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-theme-types.ts +++ b/packages/react-charts/src/components/ChartUtils/chart-theme-types.ts @@ -1,94 +1,106 @@ -import cloneDeep from 'lodash/cloneDeep'; - import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; -import { - ChartAxisTheme, - ChartBulletComparativeErrorMeasureTheme, - ChartBulletComparativeMeasureTheme, - ChartBulletComparativeWarningMeasureTheme, - ChartBulletGroupTitleTheme, - ChartBulletPrimaryDotMeasureTheme, - ChartBulletPrimaryNegativeMeasureTheme, - ChartBulletPrimarySegmentedMeasureTheme, - ChartBulletTheme, - ChartBulletQualitativeRangeTheme, - ChartDonutTheme, - ChartDonutUtilizationDynamicTheme, - ChartDonutUtilizationStaticTheme, - ChartDonutThresholdDynamicTheme, - ChartDonutThresholdStaticTheme, - ChartThresholdTheme -} from '../ChartTheme/ChartThemeTypes'; -import { getTheme, getCustomTheme } from './chart-theme'; +import { getComponentTheme, getTheme } from './chart-theme'; +import merge from 'lodash/merge'; /** * Returns axis theme * @private */ -export const getAxisTheme = (themeColor: string): ChartThemeDefinition => getCustomTheme(themeColor, ChartAxisTheme); +export const getAxisTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.axis); +}; /** * Returns bullet chart theme * @private */ -export const getBulletTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletTheme); +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 */ -export const getBulletComparativeErrorMeasureTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletComparativeErrorMeasureTheme); +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 */ -export const getBulletComparativeMeasureTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletComparativeMeasureTheme); +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 */ -export const getBulletComparativeWarningMeasureTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletComparativeWarningMeasureTheme); +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 */ -export const getBulletGroupTitleTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletGroupTitleTheme); +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 */ -export const getBulletPrimaryDotMeasureTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletPrimaryDotMeasureTheme); +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 */ -export const getBulletPrimaryNegativeMeasureTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletPrimaryNegativeMeasureTheme); +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 */ -export const getBulletPrimarySegmentedMeasureTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletPrimarySegmentedMeasureTheme); +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 */ -export const getBulletQualitativeRangeTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartBulletQualitativeRangeTheme); +export const getBulletQualitativeRangeTheme = (themeColor: string): ChartThemeDefinition => { + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.bulletQualitativeRange); +}; /** * Returns theme for Chart component @@ -99,13 +111,13 @@ export const getChartTheme = (themeColor: string, showAxis: boolean): ChartTheme if (!showAxis) { theme.axis.padding = 0; - theme.axis.style.axis.fill = 'none'; - theme.axis.style.axis.stroke = 'none'; - theme.axis.style.grid.fill = 'none'; - theme.axis.style.grid.stroke = 'none'; - theme.axis.style.ticks.fill = 'none'; - theme.axis.style.ticks.stroke = 'none'; - theme.axis.style.tickLabels.fill = 'none'; + 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; }; @@ -114,21 +126,20 @@ export const getChartTheme = (themeColor: string, showAxis: boolean): ChartTheme * Returns donut theme * @private */ -export const getDonutTheme = (themeColor: string): ChartThemeDefinition => getCustomTheme(themeColor, ChartDonutTheme); +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 */ export const getDonutThresholdDynamicTheme = (themeColor: string): ChartThemeDefinition => { - const theme = getCustomTheme(themeColor, 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; + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.donutThresholdDynamic); }; /** @@ -136,11 +147,15 @@ export const getDonutThresholdDynamicTheme = (themeColor: string): ChartThemeDef * @private */ export const getDonutThresholdStaticTheme = (themeColor: string, invert?: boolean): ChartThemeDefinition => { - const staticTheme = cloneDeep(ChartDonutThresholdStaticTheme); - if (invert && staticTheme.pie.colorScale instanceof Array) { - staticTheme.pie.colorScale = staticTheme.pie.colorScale.reverse(); + 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 getCustomTheme(themeColor, staticTheme); + return theme; }; /** @@ -148,17 +163,17 @@ export const getDonutThresholdStaticTheme = (themeColor: string, invert?: boolea * @private */ export const getDonutUtilizationTheme = (themeColor: string): ChartThemeDefinition => { - const theme = getCustomTheme(themeColor, 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; + const baseTheme = getTheme(themeColor); + const componentTheme = getComponentTheme(themeColor); + return merge(baseTheme, componentTheme.donutUtilization); }; /** * Returns threshold theme * @private */ -export const getThresholdTheme = (themeColor: string): ChartThemeDefinition => - getCustomTheme(themeColor, ChartThresholdTheme); +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/components/ChartUtils/chart-theme.ts b/packages/react-charts/src/components/ChartUtils/chart-theme.ts index b8f7e41b0b7..fda782d2ef0 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-theme.ts +++ b/packages/react-charts/src/components/ChartUtils/chart-theme.ts @@ -1,16 +1,24 @@ +import cloneDeep from 'lodash/cloneDeep'; import merge from 'lodash/merge'; import { ChartThemeColor } from '../ChartTheme/ChartThemeColor'; -import { ChartThemeDefinition } from '../ChartTheme/ChartTheme'; -import { ChartBaseTheme } from '../ChartTheme/ChartThemeTypes'; -import { BlueColorTheme } from '../ChartTheme/themes/colors/blue-theme'; -import { CyanColorTheme } from '../ChartTheme/themes/colors/cyan-theme'; -import { GoldColorTheme } from '../ChartTheme/themes/colors/gold-theme'; -import { GrayColorTheme } from '../ChartTheme/themes/colors/gray-theme'; -import { GreenColorTheme } from '../ChartTheme/themes/colors/green-theme'; -import { MultiColorOrderedTheme } from '../ChartTheme/themes/colors/multi-ordered-theme'; -import { MultiColorUnorderedTheme } from '../ChartTheme/themes/colors/multi-unordered-theme'; -import { OrangeColorTheme } from '../ChartTheme/themes/colors/orange-theme'; -import { PurpleColorTheme } from '../ChartTheme/themes/colors/purple-theme'; +import { ChartThemeDefinition, ChartComponentThemeDefinition } from '../ChartTheme/ChartTheme'; +import { ChartBaseTheme, ChartBaseComponentTheme } from '../ChartTheme/ChartThemeTypes'; +import { BlueColorTheme, BlueColorComponentTheme } from '../ChartTheme/themes/colors/blue-theme'; +import { CyanColorTheme, CyanColorComponentTheme } from '../ChartTheme/themes/colors/cyan-theme'; +import { GoldColorTheme, GoldColorComponentTheme } from '../ChartTheme/themes/colors/gold-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 @@ -27,13 +35,20 @@ export const getCustomTheme = (themeColor: string, customTheme: ChartThemeDefini * @public */ export const getTheme = (themeColor: string): ChartThemeDefinition => { - // Deep clone - const baseTheme = { - ...JSON.parse(JSON.stringify(ChartBaseTheme)) - }; + const baseTheme = cloneDeep(ChartBaseTheme); return merge(baseTheme, getThemeColors(themeColor)); }; +/** + * Returns base component theme for given color + * @private + * @beta + */ +export const getComponentTheme = (themeColor: string): ChartComponentThemeDefinition => { + const theme = cloneDeep(ChartBaseComponentTheme); + return merge(theme, getThemeComponentColors(themeColor)); +}; + /** * Returns theme colors * @public @@ -59,7 +74,42 @@ export const getThemeColors = (themeColor: string) => { return OrangeColorTheme; case ChartThemeColor.purple: return PurpleColorTheme; + case ChartThemeColor.skeleton: + return SkeletonColorTheme; default: return BlueColorTheme; } }; + +/** + * Returns theme component colors + * @private + * @beta + */ +export const getThemeComponentColors = (themeColor: string) => { + switch (themeColor) { + case ChartThemeColor.blue: + return BlueColorComponentTheme; + case ChartThemeColor.cyan: + return CyanColorComponentTheme; + case ChartThemeColor.gold: + return GoldColorComponentTheme; + 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/components/ChartUtils/chart-tooltip.ts b/packages/react-charts/src/components/ChartUtils/chart-tooltip.ts index 5d7bf819b75..1be193feb2f 100644 --- a/packages/react-charts/src/components/ChartUtils/chart-tooltip.ts +++ b/packages/react-charts/src/components/ChartUtils/chart-tooltip.ts @@ -55,7 +55,7 @@ export const getCursorTooltipCenterOffset = ({ offsetCursorDimensionY = false, theme }: ChartCursorTooltipCenterOffsetInterface) => { - const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength) : 10; + 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; @@ -80,7 +80,7 @@ export const getCursorTooltipPoniterOrientation = ({ horizontal = true, theme }: ChartCursorTooltipPoniterOrientationInterface): ((props: any) => OrientationTypes) => { - const pointerLength = theme && theme.tooltip ? Helpers.evaluateProp(theme.tooltip.pointerLength) : 10; + 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 => @@ -127,13 +127,17 @@ export const getLegendTooltipSize = ({ text = '', theme }: ChartLegendTooltipFlyoutInterface) => { - const textEvaluated = Helpers.evaluateProp(text); + 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: string, index: number) => { + _text.map((item, index) => { + if (typeof item === 'number') { + return; + } + if (item) { if (item.length > maxTextLength) { maxTextLength = item.length; @@ -153,7 +157,7 @@ export const getLegendTooltipSize = ({ // Get spacing to help align legend labels and text values const spacer = 'x'; const getSpacing = (legendLabel: string, textLabel: string) => { - let spacing = ''; + let spacing = '\u00A0'; if (maxLength === 0) { return spacing; } @@ -174,7 +178,11 @@ export const getLegendTooltipSize = ({ // {name: "Dogs 1"} // {name: "Birds 4"} // {name: "Mice 3"} - const data = _text.map((label: string, index: number) => { + 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) : ''; @@ -197,7 +205,7 @@ export const getLegendTooltipSize = ({ }); // This should only use text. The row gutter changes when displaying all "no data" messages const heightDimensions = getLegendDimensions({ - legendData: _text.map((name: string) => ({ name })), + legendData: _text.map((name) => ({ name })), legendOrientation, legendProps, theme @@ -222,7 +230,7 @@ export const getLegendTooltipVisibleData = ({ textAsLegendData = false, theme }: ChartLegendTooltipVisibleDataInterface) => { - const textEvaluated = Helpers.evaluateProp(text); + const textEvaluated = Helpers.evaluateProp(text, undefined); const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; const result = []; @@ -267,7 +275,7 @@ export const getLegendTooltipVisibleText = ({ legendData, text }: ChartLegendTooltipVisibleTextInterface) => { - const textEvaluated = Helpers.evaluateProp(text); + const textEvaluated = Helpers.evaluateProp(text, undefined); const _text = Array.isArray(textEvaluated) ? textEvaluated : [textEvaluated]; const result = []; if (legendData) { @@ -285,5 +293,5 @@ export const getLegendTooltipVisibleText = ({ } } } - return result; + return result as string[] | number[]; }; diff --git a/packages/react-charts/src/components/ResizeObserver/examples/resizeObserver.md b/packages/react-charts/src/components/ResizeObserver/examples/resizeObserver.md index 0e77eac5cbb..11e5ab5ca33 100644 --- a/packages/react-charts/src/components/ResizeObserver/examples/resizeObserver.md +++ b/packages/react-charts/src/components/ResizeObserver/examples/resizeObserver.md @@ -154,6 +154,7 @@ class MultiColorChart extends React.Component { this.containerRef = React.createRef(); this.observer = () => {}; this.state = { + extraHeight: 0, width: 0 }; this.handleResize = () => { diff --git a/packages/react-charts/src/components/Skeletons/examples/skeletons.md b/packages/react-charts/src/components/Skeletons/examples/skeletons.md new file mode 100644 index 00000000000..69a6baae290 --- /dev/null +++ b/packages/react-charts/src/components/Skeletons/examples/skeletons.md @@ -0,0 +1,799 @@ +--- +id: Skeletons +section: charts +propComponents: [ + 'Chart', + 'ChartArea', + 'ChartAxis', + 'ChartBar', + 'ChartBoxPlot', + 'ChartBullet', + 'ChartDonut', + 'ChartDonutThreshold', + 'ChartDonutUtilization', + 'ChartLegend', + 'ChartLine', + 'ChartGroup', + 'ChartPie', + 'ChartScatter', + 'ChartStack', + 'ChartThreshold', + 'ChartVoronoiContainer' +] +hideDarkMode: true +beta: true +--- + +import { Chart, ChartArea, ChartAxis, ChartBar, ChartBoxPlot, ChartBullet, ChartDonut, ChartDonutThreshold, ChartDonutUtilization, ChartLegend, ChartLine, ChartGroup, ChartPie, ChartScatter, ChartStack, ChartThemeColor, ChartThreshold, ChartVoronoiContainer } from '@patternfly/react-charts'; +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)! + +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 +```js +import React from 'react'; +import { Chart, ChartArea, ChartAxis, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts'; + +export const ChartAreaSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + +
+ `${datum.name}: ${datum.y}`} constrainToVisibleArea />} + legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }]} + 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} + > + + + + + + + + +
+ + ); +} +``` + +### Bar chart +```js +import React from 'react'; +import { Chart, ChartBar, ChartAxis, ChartGroup, ChartVoronoiContainer } from '@patternfly/react-charts'; + +export const ChartBarSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + 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} + name="chart2" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + > + + + + + + + + + +
+ + ); +} +``` + +### Box plot chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartBoxPlot } from '@patternfly/react-charts'; + +export const ChartBoxPlotSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + +
+ + + + + +
+ + ); +} +``` + +### Bullet chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartBullet, ChartLegend } from '@patternfly/react-charts'; + +export const ChartBulletSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + 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={[{ name: 'Measure', y: 25 }, { name: 'Measure', y: 60 }]} + primarySegmentedMeasureLegendData={[{ name: 'Measure' }, { name: 'Measure' }]} + qualitativeRangeData={[{ name: 'Range', y: 50 }, { name: 'Range', y: 75 }]} + qualitativeRangeLegendData={[{ name: 'Range' }, { name: 'Range' }]} + subTitle="Details" + title="Text label" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + /> +
+ + ); +} +``` + +### Donut chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartDonut } from '@patternfly/react-charts'; + +export const ChartDonutSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + +
+ `${datum.x}: ${datum.y}%`} + name="chart5" + subTitle="Pets" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + title="100" + /> +
+ + ); +} +``` + +### Donut utilization chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartDonutUtilization } from '@patternfly/react-charts'; + +export const ChartDonutUtilizationSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + +
+ datum.x ? `${datum.x}: ${datum.y}%` : null} + legendData={[{ name: `Storage capacity: 75%` }, { name: 'Unused' }]} + 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} + /> +
+ + ); +} +``` + +### Donut utilization threshold +```js +import React from 'react'; +import { Chart, ChartAxis, ChartDonutThreshold, ChartDonutUtilization } from '@patternfly/react-charts'; + +export const ChartDonutUtilizationSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + 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%" + /> + +
+ + ); +} +``` + +### Line chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartLine } from '@patternfly/react-charts'; + +export const ChartLineSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + +
+ `${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}} + name="chart8" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + > + + + + + + + + + +
+ + ); +} +``` + +### Pie chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartPie } from '@patternfly/react-charts'; + +export const ChartPieSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + +
+ `${datum.x}: ${datum.y}`} + legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]} + 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} + /> +
+ + ); +} +``` + +### Scatter chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartScatter } from '@patternfly/react-charts'; + +export const ChartScatterSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + return ( + <> + +
+ `${datum.name}: ${datum.y}`} + constrainToVisibleArea + /> + } + height={275} + maxDomain={{y: 8}} + minDomain={{y: 0}} + name="chart10" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={450} + > + + + + + + +
+ + ); +} +``` + +### Stack chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartStack } from '@patternfly/react-charts'; + +export const ChartStackSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + 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="chart11" + padding={{ + bottom: 50, + left: 50, + right: 200, // Adjusted to accommodate legend + top: 50 + }} + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={600} + > + + + + + + + + + +
+ + ); +} +``` + +### Threshold chart +```js +import React from 'react'; +import { Chart, ChartAxis, ChartThreshold } from '@patternfly/react-charts'; +import chart_color_blue_300 from '@patternfly/react-tokens/dist/esm/chart_color_blue_300'; + +export const ChartThresholdSkeleton: React.FunctionComponent = () => { + const [isChecked, setIsChecked] = React.useState(true); + + const handleChange = (_event: React.FormEvent, checked: boolean) => { + setIsChecked(checked); + }; + + 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="chart12" + themeColor={isChecked ? ChartThemeColor.skeleton : ChartThemeColor.blue} + width={800} + > + + + + + + + + +
+ + ); +} +``` + +## 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-code-editor/README.md b/packages/react-code-editor/README.md index 9c9343c4cb5..0b2581b8881 100644 --- a/packages/react-code-editor/README.md +++ b/packages/react-code-editor/README.md @@ -2,31 +2,28 @@ 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 18, use the following: +or +```sh +npm install @patternfly/react-code-editor ``` -nvm install 18 -nvm use 18 -``` - -This project also requires a Yarn version of >=1.6.0. The latest version can be installed [here](https://yarnpkg.com/). -### Installing +[!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 +```sh +yarn add --dev monaco-editor ``` or -``` -npm install @patternfly/react-code-editor +```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: diff --git a/packages/react-code-editor/package.json b/packages/react-code-editor/package.json index 194c596394a..3e032e6e2a0 100644 --- a/packages/react-code-editor/package.json +++ b/packages/react-code-editor/package.json @@ -35,15 +35,13 @@ "@patternfly/react-icons": "^6.0.0-alpha.22", "@patternfly/react-styles": "^6.0.0-alpha.22", "react-dropzone": "14.2.3", - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "peerDependencies": { "react": "^17 || ^18", "react-dom": "^17 || ^18" }, "devDependencies": { - "monaco-editor": "^0.47.0", - "rimraf": "^2.6.2", - "typescript": "^4.7.4" + "monaco-editor": "^0.49.0" } } 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/CONTRIBUTING.md b/packages/react-core/CONTRIBUTING.md index e1d84283a7d..8ce6f8e1bc3 100644 --- a/packages/react-core/CONTRIBUTING.md +++ b/packages/react-core/CONTRIBUTING.md @@ -66,8 +66,6 @@ $ git checkout -b my-branch -t upstream/main While developing, you can run the patternfly-react workspace to view the component docs with live examples. -**Note:** Be sure you are using node version >= 18.0.0 - ```bash # Start up the workspace locally on port 8002 yarn install && yarn start diff --git a/packages/react-core/package.json b/packages/react-core/package.json index ebc85f5a642..f7ac5f048a9 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -41,7 +41,7 @@ "scripts": { "build:umd": "rollup -c --environment IS_PRODUCTION", "build:single:packages": "node ../../scripts/build-single-packages.js --config single-packages.config.json", - "clean": "rimraf dist components layouts helpers next deprecated node_modules", + "clean": "rimraf dist components layouts helpers next deprecated", "generate": "node scripts/copyStyles.js", "subpaths": "node ../../scripts/exportSubpaths.js --config subpaths.config.json", "clean:exports": "node scripts/cleanDistExports.js" @@ -50,25 +50,16 @@ "@patternfly/react-icons": "^6.0.0-alpha.22", "@patternfly/react-styles": "^6.0.0-alpha.22", "@patternfly/react-tokens": "^6.0.0-alpha.22", - "focus-trap": "7.5.2", + "focus-trap": "7.5.4", "react-dropzone": "^14.2.3", - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "devDependencies": { "@patternfly/patternfly": "6.0.0-alpha.139", - "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-node-resolve": "^15.0.2", - "@rollup/plugin-replace": "^5.0.2", "case-anything": "^2.1.13", "css": "^2.2.3", "fs-extra": "^11.1.1", - "glob": "^7.1.2", - "rimraf": "^3.0.2", - "rollup": "^3.21.5", - "rollup-plugin-scss": "^4.0.0", - "rollup-plugin-svg": "2.0.0", - "rollup-plugin-terser": "^7.0.2", - "typescript": "^4.7.4" + "glob": "^7.1.2" }, "peerDependencies": { "react": "^17 || ^18", 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/src/components/Accordion/__tests__/AccordionToggle.test.tsx b/packages/react-core/src/components/Accordion/__tests__/AccordionToggle.test.tsx index d86677109bb..ca45a0b2c0d 100644 --- a/packages/react-core/src/components/Accordion/__tests__/AccordionToggle.test.tsx +++ b/packages/react-core/src/components/Accordion/__tests__/AccordionToggle.test.tsx @@ -239,6 +239,34 @@ test('Renders toggle icon before toggle text when togglePosition from context = 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( diff --git a/packages/react-core/src/components/Checkbox/examples/Checkbox.md b/packages/react-core/src/components/Checkbox/examples/Checkbox.md index ec4499f7693..2d52497d450 100644 --- a/packages/react-core/src/components/Checkbox/examples/Checkbox.md +++ b/packages/react-core/src/components/Checkbox/examples/Checkbox.md @@ -20,6 +20,20 @@ propComponents: ['Checkbox'] ``` +### Reversed + +```ts file="./CheckboxReversed.tsx" + +``` + +### Label wraps + +You can expand the clickable area of a checkbox so that it spans wider than the checkbox label by adding the `isLabelWrapped` property. This allows users to select a checkbox by clicking the checkbox itself, the label, or the area between the checkbox and the label. + +```ts file="./CheckboxLabelWraps.tsx" + +``` + ### Disabled ```ts file='./CheckboxDisabled.tsx' diff --git a/packages/react-core/src/components/Checkbox/examples/CheckboxLabelWraps.tsx b/packages/react-core/src/components/Checkbox/examples/CheckboxLabelWraps.tsx new file mode 100644 index 00000000000..256d9de82b7 --- /dev/null +++ b/packages/react-core/src/components/Checkbox/examples/CheckboxLabelWraps.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { Checkbox } from '@patternfly/react-core'; + +export const CheckboxLabelWraps: React.FunctionComponent = () => ( + +); diff --git a/packages/react-core/src/components/Checkbox/examples/CheckboxReversed.tsx b/packages/react-core/src/components/Checkbox/examples/CheckboxReversed.tsx new file mode 100644 index 00000000000..58b301be18b --- /dev/null +++ b/packages/react-core/src/components/Checkbox/examples/CheckboxReversed.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { Checkbox } from '@patternfly/react-core'; + +export const CheckboxReversed: React.FunctionComponent = () => ( + +); diff --git a/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md b/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md index 4e0c7775ffa..ccc822baa9c 100644 --- a/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md +++ b/packages/react-core/src/components/CodeBlock/examples/CodeBlock.md @@ -8,14 +8,20 @@ propComponents: ['CodeBlock', 'CodeBlockAction', 'CodeBlockCode'] import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; +**Important note:** to format code exactly as it is, you should use String.raw\`your code here\`. + +Using **String.raw\`\`** will keep all the special characters like `\n` or `\t`. + ## Examples ### Basic ```ts file="./CodeBlockBasic.tsx" + ``` ### Expandable ```ts file="./CodeBlockExpandable.tsx" + ``` diff --git a/packages/react-core/src/components/CodeBlock/examples/CodeBlockBasic.tsx b/packages/react-core/src/components/CodeBlock/examples/CodeBlockBasic.tsx index 49131aceb6c..e1e818af8bf 100644 --- a/packages/react-core/src/components/CodeBlock/examples/CodeBlockBasic.tsx +++ b/packages/react-core/src/components/CodeBlock/examples/CodeBlockBasic.tsx @@ -14,7 +14,7 @@ export const BasicCodeBlock: React.FunctionComponent = () => { setCopied(true); }; - const code = `apiVersion: helm.openshift.io/v1beta1/ + const code = String.raw`apiVersion: helm.openshift.io/v1beta1/ kind: HelmChartRepository metadata: name: azure-sample-repo0oooo00ooo diff --git a/packages/react-core/src/components/CodeBlock/examples/CodeBlockExpandable.tsx b/packages/react-core/src/components/CodeBlock/examples/CodeBlockExpandable.tsx index 1d068c18929..203f992c923 100644 --- a/packages/react-core/src/components/CodeBlock/examples/CodeBlockExpandable.tsx +++ b/packages/react-core/src/components/CodeBlock/examples/CodeBlockExpandable.tsx @@ -27,7 +27,7 @@ export const ExpandableCodeBlock: React.FunctionComponent = () => { setCopied(true); }; - const copyBlock = `apiVersion: helm.openshift.io/v1beta1/ + const copyBlock = String.raw`apiVersion: helm.openshift.io/v1beta1/ kind: HelmChartRepository metadata: name: azure-sample-repo @@ -35,11 +35,11 @@ spec: connectionConfig: url: https://raw.githubusercontent.com/Azure-Samples/helm-charts/master/docs`; - const code = `apiVersion: helm.openshift.io/v1beta1/ + const code = String.raw`apiVersion: helm.openshift.io/v1beta1/ kind: HelmChartRepository metadata: name: azure-sample-repo`; - const expandedCode = `spec: + const expandedCode = String.raw`spec: connectionConfig: url: https://raw.githubusercontent.com/Azure-Samples/helm-charts/master/docs`; diff --git a/packages/react-core/src/components/DatePicker/DatePicker.tsx b/packages/react-core/src/components/DatePicker/DatePicker.tsx index 190e4d158e2..dbe306ce54a 100644 --- a/packages/react-core/src/components/DatePicker/DatePicker.tsx +++ b/packages/react-core/src/components/DatePicker/DatePicker.tsx @@ -144,18 +144,24 @@ const DatePickerBase = ( setValueDate(dateParse(valueProp)); }, [valueProp]); + React.useEffect(() => { + if (isValidDate(valueDate)) { + applyValidators(valueDate); + } + }, [validators]); + React.useEffect(() => { setPristine(!value); const newValueDate = dateParse(value); if (errorText && isValidDate(newValueDate)) { - setError(newValueDate); + applyValidators(newValueDate); } if (value === '' && !pristine && !textInputFocused) { dateIsRequired ? setErrorText(emptyDateText) : setErrorText(''); } }, [value]); - const setError = (date: Date) => { + const applyValidators = (date: Date) => { setErrorText(validators.map((validator) => validator(date)).join('\n') || ''); }; @@ -179,7 +185,7 @@ const DatePickerBase = ( onBlur(event, value, onBlurDateArg); if (dateIsValid) { - setError(newValueDate); + applyValidators(newValueDate); } if (!dateIsValid && !pristine) { @@ -195,7 +201,7 @@ const DatePickerBase = ( const newValue = dateFormat(newValueDate); setValue(newValue); setValueDate(newValueDate); - setError(newValueDate); + applyValidators(newValueDate); setPopoverOpen(false); onChange(null, newValue, new Date(newValueDate)); }; @@ -203,7 +209,7 @@ const DatePickerBase = ( const onKeyPress = (ev: React.KeyboardEvent) => { if (ev.key === 'Enter' && value) { if (isValidDate(valueDate)) { - setError(valueDate); + applyValidators(valueDate); } else { setErrorText(invalidFormatText); } diff --git a/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx b/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx index 2319ccd2943..20b06d6640c 100644 --- a/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx +++ b/packages/react-core/src/components/Drawer/DrawerPanelContent.tsx @@ -37,13 +37,13 @@ export interface DrawerPanelContentProps extends Omit void; - /** The minimum size of a drawer, in either pixels or percentage. */ + /** 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; diff --git a/packages/react-core/src/components/Drawer/__tests__/DrawerPanelContent.test.tsx b/packages/react-core/src/components/Drawer/__tests__/DrawerPanelContent.test.tsx index afdbf1c1a89..b1cd0fe850e 100644 --- a/packages/react-core/src/components/Drawer/__tests__/DrawerPanelContent.test.tsx +++ b/packages/react-core/src/components/Drawer/__tests__/DrawerPanelContent.test.tsx @@ -36,6 +36,8 @@ test(`Renders with class ${styles.modifiers.secondary} when colorVariant="second jest.mock('../../../helpers/GenerateId/GenerateId'); +jest.mock('../../../helpers/GenerateId/GenerateId'); + test('Does not render with aria-labelledby by default', () => { render( diff --git a/packages/react-core/src/components/Label/Label.tsx b/packages/react-core/src/components/Label/Label.tsx index 78bef70da64..a7ef95fd576 100644 --- a/packages/react-core/src/components/Label/Label.tsx +++ b/packages/react-core/src/components/Label/Label.tsx @@ -311,7 +311,7 @@ export const Label: React.FunctionComponent = ({ ...editableProps }), ...(isClickableDisabled && isButton && { disabled: true }), - ...(isClickableDisabled && href && { tabindex: -1, 'aria-disabled': true }) + ...(isClickableDisabled && href && { tabIndex: -1, 'aria-disabled': true }) }; let labelComponentChild = ( diff --git a/packages/react-core/src/components/Label/__tests__/Label.test.tsx b/packages/react-core/src/components/Label/__tests__/Label.test.tsx index 519d99969cd..57600d48a5c 100644 --- a/packages/react-core/src/components/Label/__tests__/Label.test.tsx +++ b/packages/react-core/src/components/Label/__tests__/Label.test.tsx @@ -142,6 +142,93 @@ describe('Label', () => { await user.click(label); - expect(mockCallback).toBeCalledTimes(1); + expect(mockCallback).toHaveBeenCalledTimes(1); + }); + + test('disabled clickable label does not call passed callback on click', async () => { + const mockCallback = jest.fn(); + const user = userEvent.setup(); + + render( + + ); + + const label = screen.getByText('Click me'); + + await user.click(label); + + expect(mockCallback).not.toHaveBeenCalled(); + }); + + test('disabled clickable label is a disabled button', async () => { + const mockCallback = jest.fn(); + + render( + + ); + + const labelButton = screen.getByRole('button'); + + expect(labelButton).toHaveAttribute('disabled'); + }); + + test('link label is an anchor', () => { + const href = '#example'; + + render(); + + const anchor = screen.getByRole('link', { name: 'Click me' }); + + expect(anchor).toBeInTheDocument(); + expect(anchor).toHaveAttribute('href', href); + }); + + test('disabled link label is an anchor with aria-disabled attribute', () => { + const href = '#example'; + + render( + + ); + + const anchor = screen.getByRole('link', { name: 'Click me' }); + + expect(anchor).toBeInTheDocument(); + expect(anchor).toHaveAttribute('href', href); + expect(anchor).toHaveAttribute('tabIndex', '-1'); + expect(anchor).toHaveAttribute('aria-disabled', 'true'); + }); + + test('disabled removable clickable label has a disabled close button', async () => { + const mockCallback = jest.fn(); + + render( + + ); + + const closeButton = screen.getByLabelText('Close Click me'); + + expect(closeButton).toBeDisabled(); + }); + + test('disabled removable link label has a disabled close button', async () => { + const mockCallback = jest.fn(); + + render( + + ); + + const closeButton = screen.getByLabelText('Close Click me'); + + expect(closeButton).toBeDisabled(); }); }); diff --git a/packages/react-core/src/components/Label/examples/LabelCompact.tsx b/packages/react-core/src/components/Label/examples/LabelCompact.tsx index 06d7d1de31e..fb737ca6a44 100644 --- a/packages/react-core/src/components/Label/examples/LabelCompact.tsx +++ b/packages/react-core/src/components/Label/examples/LabelCompact.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Label } from '@patternfly/react-core'; import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon'; +import InfoCircleIcon from '@patternfly/react-icons/dist/esm/icons/info-circle-icon'; export const LabelCompact: React.FunctionComponent = () => ( @@ -65,6 +66,18 @@ export const LabelCompact: React.FunctionComponent = () => ( textMaxWidth="16ch" > Compact label with icon that overflows + {' '} + {' '} + ); diff --git a/packages/react-core/src/components/MenuToggle/MenuToggle.tsx b/packages/react-core/src/components/MenuToggle/MenuToggle.tsx index f432b320b57..1c1254cd2d9 100644 --- a/packages/react-core/src/components/MenuToggle/MenuToggle.tsx +++ b/packages/react-core/src/components/MenuToggle/MenuToggle.tsx @@ -129,6 +129,7 @@ class MenuToggleBase extends React.Component { aria-expanded={isExpanded} onClick={onClick} aria-label={ariaLabel || 'Menu toggle'} + tabIndex={-1} > {toggleControls} diff --git a/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap b/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap index e2b74e81ddd..cc56942d1de 100644 --- a/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap +++ b/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap @@ -871,10 +871,7 @@ exports[`Nav Nav List with flyout 1`] = `
Flyout test diff --git a/packages/react-core/src/components/NotificationDrawer/NotificationDrawerGroup.tsx b/packages/react-core/src/components/NotificationDrawer/NotificationDrawerGroup.tsx index db4cd38906a..23baf293dfb 100644 --- a/packages/react-core/src/components/NotificationDrawer/NotificationDrawerGroup.tsx +++ b/packages/react-core/src/components/NotificationDrawer/NotificationDrawerGroup.tsx @@ -22,7 +22,7 @@ export interface NotificationDrawerGroupProps extends Omit void; /** Notification drawer group title */ - title: string | React.ReactNode; + title: React.ReactNode; /** Truncate title to number of lines */ truncateTitle?: number; /** Position of the tooltip which is displayed if text is truncated */ diff --git a/packages/react-core/src/components/NumberInput/NumberInput.tsx b/packages/react-core/src/components/NumberInput/NumberInput.tsx index a7338ac13a1..7c602d609b1 100644 --- a/packages/react-core/src/components/NumberInput/NumberInput.tsx +++ b/packages/react-core/src/components/NumberInput/NumberInput.tsx @@ -67,8 +67,10 @@ const defaultKeyDownHandler = (args: DefaultKeyDownHandlerArgs) => (event: React } }; +const DEFAULT_VALUE = 0; + export const NumberInput: React.FunctionComponent = ({ - value = 0, + value = DEFAULT_VALUE, className, widthChars, isDisabled = false, @@ -122,7 +124,7 @@ export const NumberInput: React.FunctionComponent = ({
); - const panelContent = {notificationDrawer}; + const panelContent = ( + + {notificationDrawer} + + ); return ( diff --git a/packages/react-core/src/components/Pagination/Navigation.tsx b/packages/react-core/src/components/Pagination/Navigation.tsx index 4072166aac3..1ab46102fb9 100644 --- a/packages/react-core/src/components/Pagination/Navigation.tsx +++ b/packages/react-core/src/components/Pagination/Navigation.tsx @@ -29,7 +29,7 @@ export interface NavigationProps extends React.HTMLProps { /** Label for the English word "of". */ ofWord?: string; /** The number of the current page. */ - page: string | number; + page: number; /** The title of a page displayed beside the page number. */ pagesTitle?: string; /** The title of a page displayed beside the page number (the plural form). */ @@ -55,13 +55,13 @@ export interface NavigationProps extends React.HTMLProps { /** Function called when user clicks to navigate to previous page. */ onPreviousClick?: (event: React.SyntheticEvent, page: number) => void; /** Function called when user inputs page number. */ - onPageInput?: (event: React.SyntheticEvent, page: number) => void; + onPageInput?: (event: React.KeyboardEvent, page: number) => void; /** Function called when page is changed. */ onSetPage: OnSetPage; } export interface NavigationState { - userInputPage?: React.ReactText; + userInputPage?: number | string; } class Navigation extends React.Component { @@ -93,7 +93,7 @@ class Navigation extends React.Component { onPageInput: () => undefined as any }; - private static parseInteger(input: React.ReactText, lastPage: number): number { + private static parseInteger(input: number | string, lastPage: number): number { // eslint-disable-next-line radix let inputPage = Number.parseInt(input as string, 10); if (!Number.isNaN(inputPage)) { @@ -105,14 +105,14 @@ class Navigation extends React.Component { private onChange(event: React.FormEvent, lastPage: number): void { const inputPage = Navigation.parseInteger(event.currentTarget.value, lastPage); - this.setState({ userInputPage: Number.isNaN(inputPage as number) ? event.currentTarget.value : inputPage }); + this.setState({ userInputPage: Number.isNaN(inputPage) ? event.currentTarget.value : inputPage }); } private onKeyDown( event: React.KeyboardEvent, - page: number | string, + page: number, lastPage: number, - onPageInput: (event: React.SyntheticEvent, page: number) => void + onPageInput: (event: React.KeyboardEvent, page: number) => void ): void { const allowedKeys = [ 'Tab', @@ -126,9 +126,9 @@ class Navigation extends React.Component { 'ArrowDown' ]; if (event.key === KeyTypes.Enter) { - const inputPage = Navigation.parseInteger(this.state.userInputPage, lastPage) as number; - onPageInput(event, Number.isNaN(inputPage) ? (page as number) : inputPage); - this.handleNewPage(event, Number.isNaN(inputPage) ? (page as number) : inputPage); + const inputPage = Navigation.parseInteger(this.state.userInputPage, lastPage); + onPageInput(event, Number.isNaN(inputPage) ? page : inputPage); + this.handleNewPage(event, Number.isNaN(inputPage) ? page : inputPage); } else if (!/^\d*$/.test(event.key) && !allowedKeys.includes(event.key)) { event.preventDefault(); } @@ -206,7 +206,7 @@ class Navigation extends React.Component { isDisabled={isDisabled || page === firstPage || page === 0} data-action="previous" onClick={(event) => { - const newPage = (page as number) - 1 >= 1 ? (page as number) - 1 : 1; + const newPage = page - 1 >= 1 ? page - 1 : 1; onPreviousClick(event, newPage); this.handleNewPage(event, newPage); this.setState({ userInputPage: newPage }); @@ -244,7 +244,7 @@ class Navigation extends React.Component { aria-label={toNextPageAriaLabel} data-action="next" onClick={(event) => { - const newPage = (page as number) + 1 <= lastPage ? (page as number) + 1 : lastPage; + const newPage = page + 1 <= lastPage ? page + 1 : lastPage; onNextClick(event, newPage); this.handleNewPage(event, newPage); this.setState({ userInputPage: newPage }); diff --git a/packages/react-core/src/components/Pagination/Pagination.tsx b/packages/react-core/src/components/Pagination/Pagination.tsx index 60420953b42..ed4fac082ea 100644 --- a/packages/react-core/src/components/Pagination/Pagination.tsx +++ b/packages/react-core/src/components/Pagination/Pagination.tsx @@ -148,7 +148,7 @@ export interface PaginationProps extends React.HTMLProps, OUIAPr /** Function called when user clicks on navigate to next page. */ onNextClick?: (event: React.SyntheticEvent, page: number) => void; /** Function called when user inputs page number. */ - onPageInput?: (event: React.SyntheticEvent, page: number) => void; + onPageInput?: (event: React.KeyboardEvent, page: number) => void; /** Function called when user selects number of items per page. */ onPerPageSelect?: OnPerPageSelect; /** Function called when user clicks on navigate to previous page. */ @@ -232,6 +232,7 @@ export const Pagination: React.FunctionComponent = ({ ...props }: PaginationProps) => { const paginationRef = React.useRef(null); + const containerRef = React.useRef(null); const getLastPage = () => // when itemCount is not known let's set lastPage as page+1 as we don't know the total count @@ -334,6 +335,7 @@ export const Pagination: React.FunctionComponent = ({ widgetId={`${widgetId}-${variant}`} toggleTemplate={toggleTemplate} isDisabled={isDisabled} + containerRef={containerRef} /> )} ; } export const PaginationOptionsMenu: React.FunctionComponent = ({ @@ -75,12 +75,12 @@ export const PaginationOptionsMenu: React.FunctionComponent null as any + onPerPageSelect = () => null as any, + containerRef }: PaginationOptionsMenuProps) => { const [isOpen, setIsOpen] = React.useState(false); const toggleRef = React.useRef(null); const menuRef = React.useRef(null); - const containerRef = React.useRef(null); const onToggle = () => { setIsOpen((prevState) => !prevState); @@ -209,18 +209,16 @@ export const PaginationOptionsMenu: React.FunctionComponent - -
+ ); }; diff --git a/packages/react-core/src/components/Pagination/__tests__/Generated/__snapshots__/PaginationOptionsMenu.test.tsx.snap b/packages/react-core/src/components/Pagination/__tests__/Generated/__snapshots__/PaginationOptionsMenu.test.tsx.snap index 03310f84ce3..9c30b5d5f7f 100644 --- a/packages/react-core/src/components/Pagination/__tests__/Generated/__snapshots__/PaginationOptionsMenu.test.tsx.snap +++ b/packages/react-core/src/components/Pagination/__tests__/Generated/__snapshots__/PaginationOptionsMenu.test.tsx.snap @@ -2,50 +2,46 @@ exports[`PaginationOptionsMenu should match snapshot (auto-generated) 1`] = ` - + + `; diff --git a/packages/react-core/src/components/Pagination/__tests__/PaginationOptionsMenu.test.tsx b/packages/react-core/src/components/Pagination/__tests__/PaginationOptionsMenu.test.tsx index 5ba7f5b61ab..98be0dc6c10 100644 --- a/packages/react-core/src/components/Pagination/__tests__/PaginationOptionsMenu.test.tsx +++ b/packages/react-core/src/components/Pagination/__tests__/PaginationOptionsMenu.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { PaginationOptionsMenu } from '../PaginationOptionsMenu'; import { render, screen } from '@testing-library/react'; -import styles from '@patternfly/react-styles/css/components/Pagination/pagination'; +import styles from '@patternfly/react-styles/css/components/Menu/menu'; jest.mock('../../../helpers/Popper/Popper'); @@ -15,9 +15,9 @@ test('renders pagination options menu', () => { expect(screen.getByTestId('options-menu').children[0]).toBeVisible(); }); -test(`renders with class ${styles.paginationPageMenu} by default`, () => { +test(`renders with class ${styles.menu} by default`, () => { render(); // Mocked Popper is rendered with data-testid="mock-wrapper" - expect(screen.getByTestId('mock-wrapper').parentElement).toHaveClass(styles.paginationPageMenu); + expect(screen.getByTestId('mock-wrapper').parentElement).toHaveClass(styles.menu); }); diff --git a/packages/react-core/src/components/Pagination/__tests__/__snapshots__/Pagination.test.tsx.snap b/packages/react-core/src/components/Pagination/__tests__/__snapshots__/Pagination.test.tsx.snap index 1cd5e00f396..0184752622c 100644 --- a/packages/react-core/src/components/Pagination/__tests__/__snapshots__/Pagination.test.tsx.snap +++ b/packages/react-core/src/components/Pagination/__tests__/__snapshots__/Pagination.test.tsx.snap @@ -22,51 +22,47 @@ exports[`Pagination API verify inset2xl inset breakpoints 1`] = ` - + +