diff --git a/packages/react-core/src/components/Select/examples/Select.md b/packages/react-core/src/components/Select/examples/Select.md index 3fe39843a71..94f65e59d62 100644 --- a/packages/react-core/src/components/Select/examples/Select.md +++ b/packages/react-core/src/components/Select/examples/Select.md @@ -15,6 +15,8 @@ import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; Select builds off of the menu component suite to adapt commonly used properties and functions to create a select menu. See the [menu documentation](/components/menus/menu) for a full list of properties that may be used to further customize a select menu. View the [custom menu examples](/components/menus/custom-menus) to see examples of fully functional select menus. +For use cases that do not require a lot of customization, there are various template components available to use in the `@react-templates` package. These templates have a streamlined API and logic, making them easier to set up and use, but are limited in scope and flexibility. See the [templates page](/components/menus/select/react-templates) for details. + ### Single select To let users select a single item from a list, use a single select menu. diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index ecbb93f6406..f91de8a4f72 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -30,7 +30,8 @@ "@patternfly/react-icons": "^5.3.0-prerelease.3", "@patternfly/react-styles": "^5.3.0-prerelease.3", "@patternfly/react-table": "^5.3.0-prerelease.18", - "@patternfly/react-tokens": "^5.3.0-prerelease.3" + "@patternfly/react-tokens": "^5.3.0-prerelease.3", + "@patternfly/react-templates": "^1.0.0-alpha.0" }, "devDependencies": { "@patternfly/documentation-framework": "^5.8.2", diff --git a/packages/react-docs/patternfly-docs/patternfly-docs.source.js b/packages/react-docs/patternfly-docs/patternfly-docs.source.js index 0d6f20116d6..b04b4effea9 100644 --- a/packages/react-docs/patternfly-docs/patternfly-docs.source.js +++ b/packages/react-docs/patternfly-docs/patternfly-docs.source.js @@ -17,6 +17,7 @@ module.exports = (baseSourceMD, sourceProps) => { .resolve('@patternfly/react-code-editor/package.json') .replace('package.json', 'src'); const reactDragDropPath = require.resolve('@patternfly/react-drag-drop/package.json').replace('package.json', 'src'); + const reactTemplatesPath = require.resolve('@patternfly/react-templates/package.json').replace('package.json', 'src'); const reactPropsIgnore = '**/*.test.tsx'; sourceProps(path.join(reactCorePath, '/**/*.tsx'), reactPropsIgnore); @@ -24,6 +25,7 @@ module.exports = (baseSourceMD, sourceProps) => { sourceProps(path.join(reactChartsPath, '/**/*.tsx'), reactPropsIgnore); sourceProps(path.join(reactCodeEditorPath, '/**/*.tsx'), reactPropsIgnore); sourceProps(path.join(reactDragDropPath, '/**/*.tsx'), reactPropsIgnore); + sourceProps(path.join(reactTemplatesPath, '/**/*.tsx'), reactPropsIgnore); // React MD sourceMD(path.join(reactCorePath, '/components/**/examples/*.md'), 'react'); @@ -46,6 +48,9 @@ module.exports = (baseSourceMD, sourceProps) => { // Drag drop MD sourceMD(path.join(reactDragDropPath, '/**/examples/*.md'), 'react-next'); + // Templates MD + sourceMD(path.join(reactTemplatesPath, '/**/examples/*.md'), 'react-templates'); + // OUIA MD sourceMD(path.join(reactCorePath, 'helpers/OUIA/OUIA.md'), 'react'); }; diff --git a/packages/react-templates/.gitignore b/packages/react-templates/.gitignore new file mode 100644 index 00000000000..480a54dbfce --- /dev/null +++ b/packages/react-templates/.gitignore @@ -0,0 +1,2 @@ +/deprecated +/components \ No newline at end of file diff --git a/packages/react-templates/.npmignore b/packages/react-templates/.npmignore new file mode 100644 index 00000000000..491b5aeb360 --- /dev/null +++ b/packages/react-templates/.npmignore @@ -0,0 +1,2 @@ +dist/*.tsbuildinfo +tsconfig.* \ No newline at end of file diff --git a/packages/react-templates/CHANGELOG.md b/packages/react-templates/CHANGELOG.md new file mode 100644 index 00000000000..e4d87c4d45c --- /dev/null +++ b/packages/react-templates/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/react-templates/README.md b/packages/react-templates/README.md new file mode 100644 index 00000000000..dae23cecda9 --- /dev/null +++ b/packages/react-templates/README.md @@ -0,0 +1,42 @@ +# @patternfly/react-templates + +This package provides wrapped Patternfly component demos with a streamlined API for ease of use. + +### 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 18, use the following: + +``` +nvm install 18 +nvm use 18 +``` + +This project also requires a Yarn version of >=1.6.0. The latest version can be installed from the [Yarn](https://yarnpkg.com/) home page. + +### Installing + +``` +yarn add @patternfly/react-templates +``` + +or + +``` +npm install @patternfly/react-templates --save +``` + +### Usage + +It's strongly advised to use the PatternFly Base CSS in your whole project, or some components may diverge in appearance: + +```js +import '@patternfly/react-core/dist/styles/base.css'; +``` + +```js +import { SimpleSelect } from '@patternfly/react-templates'; +``` diff --git a/packages/react-templates/package.json b/packages/react-templates/package.json new file mode 100644 index 00000000000..58e33295b12 --- /dev/null +++ b/packages/react-templates/package.json @@ -0,0 +1,50 @@ +{ + "name": "@patternfly/react-templates", + "version": "1.0.0-alpha.0", + "description": "This package provides wrapped component demos for ease of use\n", + "main": "dist/js/index.js", + "module": "dist/esm/index.js", + "types": "dist/esm/index.d.ts", + "patternfly:src": "src/", + "sideEffects": false, + "publishConfig": { + "access": "public", + "tag": "alpha" + }, + "repository": { + "type": "git", + "url": "https://github.com/patternfly/patternfly-react.git" + }, + "keywords": [ + "react", + "patternfly", + "templates" + ], + "author": "Red Hat", + "license": "MIT", + "bugs": { + "url": "https://github.com/patternfly/patternfly-react/issues" + }, + "homepage": "https://github.com/patternfly/patternfly-react/tree/main/packages/react-templates#readme", + "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 deprecated", + "subpaths": "node ../../scripts/exportSubpaths.js --config subpaths.config.json" + }, + "dependencies": { + "@patternfly/react-core": "^5.3.0-prerelease.17", + "@patternfly/react-icons": "^5.3.0-prerelease.3", + "@patternfly/react-styles": "^5.3.0-prerelease.3", + "@patternfly/react-tokens": "^5.3.0-prerelease.3", + "tslib": "^2.5.0" + }, + "peerDependencies": { + "react": "^17 || ^18", + "react-dom": "^17 || ^18" + }, + "devDependencies": { + "rimraf": "^2.6.2", + "typescript": "^4.7.4" + } +} diff --git a/packages/react-templates/rollup.config.js b/packages/react-templates/rollup.config.js new file mode 100644 index 00000000000..aad9805a088 --- /dev/null +++ b/packages/react-templates/rollup.config.js @@ -0,0 +1,7 @@ +const { name } = require('./package.json'); +const baseConfig = require('../rollup.base'); + +module.exports = baseConfig({ + packageName: name.replace('@patternfly/', ''), + name: 'PatternFlyTemplates' +}); diff --git a/packages/react-templates/single-packages.config.json b/packages/react-templates/single-packages.config.json new file mode 100644 index 00000000000..f64497ffdac --- /dev/null +++ b/packages/react-templates/single-packages.config.json @@ -0,0 +1,4 @@ +{ + "packageName": "@patternfly/react-templates", + "exclude": ["dist/esm/deprecated/index.js", "dist/esm/next/index.js"] +} diff --git a/packages/react-templates/src/components/Select/SelectSimple.tsx b/packages/react-templates/src/components/Select/SelectSimple.tsx new file mode 100644 index 00000000000..2a5770f7822 --- /dev/null +++ b/packages/react-templates/src/components/Select/SelectSimple.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import { Select, SelectList, SelectOption, SelectOptionProps } from '@patternfly/react-core/dist/esm/components/Select'; +import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/esm/components/MenuToggle'; + +export interface SelectSimpleOption extends Omit { + /** Content of the select option. */ + content: React.ReactNode; + /** Value of the select option. */ + value: string | number; +} + +export interface SelectSimpleProps { + /** @hide Forwarded ref */ + innerRef?: React.Ref; + /** Initial options of the select. */ + initialOptions?: SelectSimpleOption[]; + /** Callback triggered on selection. */ + onSelect?: (_event: React.MouseEvent, selection: string | number) => void; + /** Callback triggered when the select opens or closes. */ + onToggle?: (nextIsOpen: boolean) => void; + /** Flag indicating the select should be disabled. */ + isDisabled?: boolean; + /** Content of the toggle. Defaults to the selected option. */ + toggleContent?: React.ReactNode; + /** Width of the toggle */ + toggleWidth?: string; +} + +const SelectSimpleBase: React.FunctionComponent = ({ + innerRef, + initialOptions, + isDisabled, + onSelect, + onToggle, + toggleContent, + toggleWidth = '200px', + ...props +}: SelectSimpleProps) => { + const [isOpen, setIsOpen] = React.useState(false); + const [selected, setSelected] = React.useState('Select a value'); + + const simpleSelectOptions = initialOptions?.map((option) => { + const { content, value, ...props } = option; + const isSelected = selected.includes(`${value}`); + return ( + + {content} + + ); + }); + + const onToggleClick = () => { + onToggle && onToggle(!isOpen); + setIsOpen(!isOpen); + }; + + const _onSelect = (_event: React.MouseEvent | undefined, value: string | number | undefined) => { + onSelect && onSelect(_event, value); + setSelected(value as string); + setIsOpen(false); + }; + + const toggle = (toggleRef: React.Ref) => ( + + {toggleContent ? toggleContent : selected} + + ); + + return ( + + ); +}; + +export const SelectSimple = React.forwardRef((props: SelectSimpleProps, ref: React.Ref) => ( + +)); + +SelectSimple.displayName = 'SelectSimple'; diff --git a/packages/react-templates/src/components/Select/examples/SelectSimpleDemo.tsx b/packages/react-templates/src/components/Select/examples/SelectSimpleDemo.tsx new file mode 100644 index 00000000000..da98bbcfcf2 --- /dev/null +++ b/packages/react-templates/src/components/Select/examples/SelectSimpleDemo.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Checkbox } from '@patternfly/react-core'; +import { SelectSimple, SelectSimpleOption } from '@patternfly/react-templates'; + +export const SelectSimpleDemo: React.FunctionComponent = () => { + const [isDisabled, setIsDisabled] = React.useState(false); + + const initialOptions: SelectSimpleOption[] = [ + { content: 'Option 1', value: 'option1' }, + { content: 'Option 2', value: 'option2' }, + { content: 'Option 3', value: 'option3' } + ]; + + return ( + + setIsDisabled(checked)} + style={{ marginBottom: 20 }} + /> + + + ); +}; diff --git a/packages/react-templates/src/components/Select/examples/SelectTemplates.md b/packages/react-templates/src/components/Select/examples/SelectTemplates.md new file mode 100644 index 00000000000..89cf3616271 --- /dev/null +++ b/packages/react-templates/src/components/Select/examples/SelectTemplates.md @@ -0,0 +1,23 @@ +--- +id: Select +section: components +subsection: menus +template: true +beta: true +propComponents: ['SimpleSelect'] +--- + +Note: Templates live in their own package at [@patternfly/react-templates](https://www.npmjs.com/package/@patternfly/react-templates)! + +For custom use cases, please see the select component suite from [@patternfly/react-core](https://www.npmjs.com/package/@patternfly/react-core). + +import { SelectOption, Checkbox } from '@patternfly/react-core'; +import { SelectSimple } from '@patternfly/react-templates'; + +## Select template examples + +### Simple + +```ts file="SelectSimpleDemo.tsx" + +``` diff --git a/packages/react-templates/src/components/Select/index.ts b/packages/react-templates/src/components/Select/index.ts new file mode 100644 index 00000000000..9c0381bfb99 --- /dev/null +++ b/packages/react-templates/src/components/Select/index.ts @@ -0,0 +1 @@ +export * from './SelectSimple'; diff --git a/packages/react-templates/src/components/index.ts b/packages/react-templates/src/components/index.ts new file mode 100644 index 00000000000..7868ecbae29 --- /dev/null +++ b/packages/react-templates/src/components/index.ts @@ -0,0 +1 @@ +export * from './Select'; diff --git a/packages/react-templates/src/index.ts b/packages/react-templates/src/index.ts new file mode 100644 index 00000000000..07635cbbc8e --- /dev/null +++ b/packages/react-templates/src/index.ts @@ -0,0 +1 @@ +export * from './components'; diff --git a/packages/react-templates/subpaths.config.json b/packages/react-templates/subpaths.config.json new file mode 100644 index 00000000000..cf89648338a --- /dev/null +++ b/packages/react-templates/subpaths.config.json @@ -0,0 +1,4 @@ +{ + "packageName": "@patternfly/react-templates", + "paths": ["components"] +} diff --git a/packages/react-templates/tsconfig.cjs.json b/packages/react-templates/tsconfig.cjs.json new file mode 100644 index 00000000000..578d46af9d3 --- /dev/null +++ b/packages/react-templates/tsconfig.cjs.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/js", + "module": "commonjs", + "tsBuildInfoFile": "dist/cjs.tsbuildinfo" + } +} diff --git a/packages/react-templates/tsconfig.json b/packages/react-templates/tsconfig.json new file mode 100644 index 00000000000..f08aeb83272 --- /dev/null +++ b/packages/react-templates/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist/esm", + "tsBuildInfoFile": "dist/esm.tsbuildinfo" + }, + "include": [ + "./src/*", + "./src/**/*" + ], + "references": [ + { + "path": "../react-core" + }, + { + "path": "../react-icons" + }, + { + "path": "../react-styles" + } + ] +} diff --git a/packages/tsconfig.cjs.json b/packages/tsconfig.cjs.json index 607146bbcac..403528429f3 100644 --- a/packages/tsconfig.cjs.json +++ b/packages/tsconfig.cjs.json @@ -21,6 +21,9 @@ }, { "path": "./react-table/tsconfig.cjs.json" + }, + { + "path": "./react-templates/tsconfig.cjs.json" } ] } diff --git a/packages/tsconfig.json b/packages/tsconfig.json index b7ea8c38508..86ee37c1e90 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -21,6 +21,9 @@ }, { "path": "./react-table" + }, + { + "path": "./react-templates" } ] } diff --git a/scripts/promote.sh b/scripts/promote.sh index 26118a1e43d..f3d33293f42 100755 --- a/scripts/promote.sh +++ b/scripts/promote.sh @@ -8,6 +8,7 @@ packages=( @patternfly/react-icons @patternfly/react-styles @patternfly/react-table + @patternfly/react-templates @patternfly/react-tokens ) prereleaseTag=prerelease diff --git a/yarn.lock b/yarn.lock index b909347e7a5..3e58aafdf96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17254,16 +17254,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17396,7 +17387,7 @@ stringify-entities@^3.0.1: is-decimal "^1.0.2" is-hexadecimal "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17415,13 +17406,6 @@ strip-ansi@^5.1.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -19504,7 +19488,7 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19522,15 +19506,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"