diff --git a/packages/module/package.json b/packages/module/package.json index 0b560b22..ecc8a105 100644 --- a/packages/module/package.json +++ b/packages/module/package.json @@ -5,9 +5,8 @@ "main": "dist/cjs/index.js", "module": "dist/esm/index.js", "scripts": { - "build": "npm run build:index && npm run build:js && npm run build:esm && npm run build:fed:packages && npm run build:css && npm run transform:scss", - "build:css": "node ../../scripts/build-styles.js", - "build:watch": "npm run build:js && npm run build:esm -- --watch && npm run build:fed:packages -- --watch && npm run build:css && npm run transform:scss", + "build": "npm run build:index && npm run build:js && npm run build:esm && npm run build:fed:packages", + "build:watch": "npm run build:js && npm run build:esm -- --watch && npm run build:fed:packages -- --watch", "build:esm": "tsc --build --verbose ./tsconfig.json", "build:fed:packages": "node generate-fed-package-json.js", "build:js": "tsc -p tsconfig.cjs.json", @@ -18,8 +17,7 @@ "docs:serve": "pf-docs-framework serve public --port 5001", "docs:screenshots": "pf-docs-framework screenshots --urlPrefix http://localhost:5001", "serve:a11y": "serve coverage", - "test:a11y": "patternfly-a11y --config patternfly-a11y.config", - "transform:scss": "node ../../scripts/transform-scss.js" + "test:a11y": "patternfly-a11y --config patternfly-a11y.config" }, "repository": "git+https://github.com/patternfly/react-component-groups.git", "author": "Red Hat", @@ -48,7 +46,6 @@ "@patternfly/patternfly": "^5.0.0", "@patternfly/react-table": "^5.0.0", "@patternfly/react-code-editor": "^5.0.0", - "@redhat-cloud-services/frontend-components-utilities": "^4.0.2", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@types/react-router-dom": "^5.3.3", diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/ExpandableText/ExpandableText.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ExpandableText/ExpandableText.md new file mode 100644 index 00000000..618aec21 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ExpandableText/ExpandableText.md @@ -0,0 +1,17 @@ +--- +section: extensions +subsection: Component groups +id: ExpandableText +source: react +propComponents: ['ExpandableText'] +--- + +import ExpandableText from "@patternfly/react-component-groups/dist/dynamic/ExpandableText"; + +## Component usage + +### Truncate component + +```js file="./ExpandableTextExample.tsx" + +``` diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/ExpandableText/ExpandableTextExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ExpandableText/ExpandableTextExample.tsx new file mode 100644 index 00000000..8e205065 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ExpandableText/ExpandableTextExample.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import ExpandableText from "@patternfly/react-component-groups/dist/dynamic/ExpandableText"; + + +export const BasicExample: React.FunctionComponent = () => ; + diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Truncate/Truncate.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Truncate/Truncate.md deleted file mode 100644 index a83da642..00000000 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Truncate/Truncate.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -section: extensions -subsection: Component groups -id: Truncate -source: react -propComponents: ['Truncate'] ---- - -import Truncate from "@patternfly/react-component-groups/dist/dynamic/Truncate"; - -## Component usage - -### Truncate component - -```js file="./TruncateExample.tsx" - -``` diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Truncate/TruncateExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Truncate/TruncateExample.tsx deleted file mode 100644 index 3ebedc2e..00000000 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Truncate/TruncateExample.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import Truncate from "@patternfly/react-component-groups/dist/dynamic/Truncate"; - - -export const BasicExample: React.FunctionComponent = () => ; - diff --git a/packages/module/src/ExpandableText/ExpandableText.test.tsx b/packages/module/src/ExpandableText/ExpandableText.test.tsx new file mode 100644 index 00000000..835a2992 --- /dev/null +++ b/packages/module/src/ExpandableText/ExpandableText.test.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import ExpandableText from './ExpandableText'; + +const text = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore +et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea +commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla +pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est +laborum.`; + +describe('ExpandableText component', () => { + describe('should render correctly', () => { + [true, false].forEach((isInline) => { + describe(isInline ? 'inline' : 'block', () => { + it('without length specified', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('with short length', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('clicking on expand toggles to collapse', () => { + const wrapper = render(); + // wrapper.find('.ins-c-expand-button').first().simulate('click'); + expect(wrapper).toMatchSnapshot(); + }); + + it('custom expande button', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('custom button titles', () => { + const wrapper = render(); + // wrapper.find('.ins-c-expand-button').first().simulate('click'); + expect(wrapper).toMatchSnapshot(); + }); + + it('clicking on expand toggles to collapse', () => { + const wrapper = render(); + // wrapper.find('.ins-c-expand-button').first().simulate('click'); + expect(wrapper).toMatchSnapshot(); + }); + + it('custom expande button', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('custom button titles', () => { + const wrapper = render(); + // wrapper.find('.ins-c-expand-button').first().simulate('click'); + expect(wrapper).toMatchSnapshot(); + }); + + it('when text length is less than user specified length', () => { + const wrapper = render(); + expect(wrapper).toMatchSnapshot(); + }); + + it('hovering over toggles to collapse', () => { + const wrapper = render(); + // const eventElement = isInline ? wrapper.find('.ins-c-ExpandableText').first() : wrapper.find('.ins-c-ExpandableText').first().children().first(); + + expect(wrapper).toMatchSnapshot(); + + // eventElement.simulate('mouseenter'); + expect(wrapper).toMatchSnapshot(); + + // eventElement.simulate('mouseleave'); + expect(wrapper).toMatchSnapshot(); + }); + }); + }); + }); +}); diff --git a/packages/module/src/Truncate/Truncate.tsx b/packages/module/src/ExpandableText/ExpandableText.tsx similarity index 62% rename from packages/module/src/Truncate/Truncate.tsx rename to packages/module/src/ExpandableText/ExpandableText.tsx index ce6c86cf..b91bb6b5 100644 --- a/packages/module/src/Truncate/Truncate.tsx +++ b/packages/module/src/ExpandableText/ExpandableText.tsx @@ -1,18 +1,26 @@ +/* eslint-disable react/no-unknown-property */ import React, { useState } from 'react'; import classNames from 'classnames'; import { Button, Stack, StackItem } from '@patternfly/react-core'; import sanitizeHtml from 'sanitize-html'; +import { createUseStyles } from 'react-jss' -import './truncate.scss'; +const useStyles = createUseStyles({ + expandableText: { + "& button": { + padding: "0" + }, + "& is-inline": { marginRight: [ "10px", "0.625rem" ] } + } }); const dangerousHtml = (html: string) => ({ __html: sanitizeHtml(html) }); -export interface TruncateProps { - /** Additional classes added to the Truncate */ +export interface ExpandableTextProps { + /** Additional classes added to the ExpandableText */ className?: string; - /** Text to display inside the Truncate component */ + /** Text to display pfcgide the ExpandableText component */ text?: string; - /** A set length for the truncate component. */ + /** A set length for the ExpandableText component. */ length?: number; /** Indicates if the component is expanded to show the entire text */ expandText?: React.ReactNode; @@ -25,7 +33,7 @@ export interface TruncateProps { expandOnMouseOver?: boolean; } -const Truncate: React.FunctionComponent = ({ +const ExpandableText: React.FunctionComponent = ({ text = '', length = 150, expandText = 'Read more', @@ -35,8 +43,9 @@ const Truncate: React.FunctionComponent = ({ className, inline, spaceBetween, -}: TruncateProps) => { - const truncateClasses = classNames('ins-c-truncate', className, { [`is-inline`]: inline }, { [`is-block`]: !inline }); +}: ExpandableTextProps) => { + const classes = useStyles(); + const expandableTextClasses = classNames(classes.expandableText, className, { [`is-inline`]: inline }, { [`is-block`]: !inline }); const trimmedText = text.substring(0, length); const textOverflow = text.length > length; const [showText, setShowText] = useState(false); @@ -46,12 +55,12 @@ const Truncate: React.FunctionComponent = ({ }; const expandButton = ( - ); const collapseButton = ( - ); @@ -64,13 +73,13 @@ const Truncate: React.FunctionComponent = ({ return inline ? ( - + {!hideExpandText && textOverflow && (showText === false ? expandButton : collapseButton)} ) : ( - + - + {!hideExpandText && textOverflow && ( = ({ ); }; -export default Truncate; +export default ExpandableText; diff --git a/packages/module/src/ExpandableText/index.ts b/packages/module/src/ExpandableText/index.ts new file mode 100644 index 00000000..fbbf83f4 --- /dev/null +++ b/packages/module/src/ExpandableText/index.ts @@ -0,0 +1,3 @@ +export { default } from './ExpandableText'; +export { default as ExpandableText } from './ExpandableText'; +export * from './ExpandableText'; diff --git a/packages/module/src/Truncate/Truncate.test.js b/packages/module/src/Truncate/Truncate.test.js deleted file mode 100644 index 06ea1fb7..00000000 --- a/packages/module/src/Truncate/Truncate.test.js +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import Truncate from './Truncate'; - -const text = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore -et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea -commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla -pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est -laborum.`; - -describe('Truncate component', () => { - describe('should render correctly', () => { - [true, false].forEach((isInline) => { - describe(isInline ? 'inline' : 'block', () => { - it('without length specified', () => { - const wrapper = render(); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('with short length', () => { - const wrapper = render(); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('clicking on expand toggles to collapse', () => { - const wrapper = render(); - wrapper.find('.ins-c-expand-button').first().simulate('click'); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('custom expande button', () => { - const wrapper = render(); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('custom button titles', () => { - const wrapper = render(); - wrapper.find('.ins-c-expand-button').first().simulate('click'); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('clicking on expand toggles to collapse', () => { - const wrapper = render(); - wrapper.find('.ins-c-expand-button').first().simulate('click'); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('custom expande button', () => { - const wrapper = render(); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('custom button titles', () => { - const wrapper = render(); - wrapper.find('.ins-c-expand-button').first().simulate('click'); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('when text length is less than user specified length', () => { - const wrapper = render(); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('hovering over toggles to collapse', () => { - const wrapper = render(); - const eventElement = isInline ? wrapper.find('.ins-c-truncate').first() : wrapper.find('.ins-c-truncate').first().children().first(); - - expect(toJson(wrapper)).toMatchSnapshot(); - - eventElement.simulate('mouseenter'); - expect(toJson(wrapper)).toMatchSnapshot(); - - eventElement.simulate('mouseleave'); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - }); - }); - }); -}); diff --git a/packages/module/src/Truncate/__snapshots__/Truncate.test.js.snap b/packages/module/src/Truncate/__snapshots__/Truncate.test.js.snap deleted file mode 100644 index 23ea4171..00000000 --- a/packages/module/src/Truncate/__snapshots__/Truncate.test.js.snap +++ /dev/null @@ -1,593 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Truncate component should render correctly block clicking on expand toggles to collapse 1`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly block clicking on expand toggles to collapse 2`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly block custom button titles 1`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly block custom button titles 2`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly block custom expande button 1`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly block custom expande button 2`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly block hovering over toggles to collapse 1`] = ` - - - - - -`; - -exports[`Truncate component should render correctly block hovering over toggles to collapse 2`] = ` - - - - - -`; - -exports[`Truncate component should render correctly block hovering over toggles to collapse 3`] = ` - - - - - -`; - -exports[`Truncate component should render correctly block when text length is less than user specified length 1`] = ` - - - - - -`; - -exports[`Truncate component should render correctly block with short length 1`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly block without length specified 1`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly inline clicking on expand toggles to collapse 1`] = ` - - - - -`; - -exports[`Truncate component should render correctly inline clicking on expand toggles to collapse 2`] = ` - - - - -`; - -exports[`Truncate component should render correctly inline custom button titles 1`] = ` - - - - -`; - -exports[`Truncate component should render correctly inline custom button titles 2`] = ` - - - - -`; - -exports[`Truncate component should render correctly inline custom expande button 1`] = ` - - - - -`; - -exports[`Truncate component should render correctly inline custom expande button 2`] = ` - - - - -`; - -exports[`Truncate component should render correctly inline hovering over toggles to collapse 1`] = ` - - - -`; - -exports[`Truncate component should render correctly inline hovering over toggles to collapse 2`] = ` - - - -`; - -exports[`Truncate component should render correctly inline hovering over toggles to collapse 3`] = ` - - - -`; - -exports[`Truncate component should render correctly inline when text length is less than user specified length 1`] = ` - - - -`; - -exports[`Truncate component should render correctly inline with short length 1`] = ` - - - - - - - - -`; - -exports[`Truncate component should render correctly inline without length specified 1`] = ` - - - - -`; diff --git a/packages/module/src/Truncate/index.ts b/packages/module/src/Truncate/index.ts deleted file mode 100644 index 34fc83dc..00000000 --- a/packages/module/src/Truncate/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default } from './Truncate'; -export { default as Truncate } from './Truncate'; -export * from './Truncate'; diff --git a/packages/module/src/Truncate/truncate.scss b/packages/module/src/Truncate/truncate.scss deleted file mode 100644 index 8e871527..00000000 --- a/packages/module/src/Truncate/truncate.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import '~@redhat-cloud-services/frontend-components-utilities/styles/_all.scss'; - -.ins-c-truncate button, .ins-c-truncate + button { padding: 0; } - -.ins-c-truncate.is-inline { @include rem('margin-right', 10px); } diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts index 025bd9b9..853f1d5d 100644 --- a/packages/module/src/index.ts +++ b/packages/module/src/index.ts @@ -18,11 +18,11 @@ export * from './ErrorStack'; export { default as ErrorState } from './ErrorState'; export * from './ErrorState'; +export { default as ExpandableText } from './ExpandableText'; +export * from './ExpandableText'; + export { default as HorizontalNav } from './HorizontalNav'; export * from './HorizontalNav'; export { default as NotAuthorized } from './NotAuthorized'; export * from './NotAuthorized'; - -export { default as Truncate } from './Truncate'; -export * from './Truncate'; diff --git a/scripts/build-styles.js b/scripts/build-styles.js deleted file mode 100644 index 9e2abc52..00000000 --- a/scripts/build-styles.js +++ /dev/null @@ -1,91 +0,0 @@ -const fs = require('fs'); -const glob = require('glob'); -const path = require('path'); -const sass = require('sass'); -const chokidar = require('chokidar'); -const packageImporter = require('node-sass-package-importer'); - -/** - * Root path of the current package - */ -const root = process.cwd(); -/** - * get all scss files - */ - -const files = glob.sync(`${root}/src/**/*.scss`); - -async function buildStyle(file) { - const outFiles = [ - path.resolve(file.replace('/src/', '/dist/cjs/'), './').replace(/scss$/, 'css'), - path.resolve(file.replace('/src/', '/dist/esm/'), './').replace(/scss$/, 'css'), - ]; - const promises = outFiles.map((outFile) => { - let targetDir = outFile.split('/'); - targetDir.pop(); - targetDir = targetDir.join('/').replace(root, '').replace(/^\//, ''); - - if (!fs.existsSync(path.resolve(root, targetDir))) { - fs.mkdirSync(targetDir); - } - - const render = sass.render( - { - file, - outFile, - importer: packageImporter(), - }, - function (err, result) { - if (err) { - console.error(file, outFile); - throw err; - } - - return fs.writeFile(outFile, result.css, 'utf8', function (err) { - if (err) { - throw err; - } - }); - } - ); - const copy = fs.copyFile(file, outFile.replace(/css$/, 'scss'), function (err) { - if (err) { - throw err; - } - }); - return Promise.all([render, copy]); - }); - return Promise.all(promises); -} - -async function buildStyles(files) { - const cmds = files.map(buildStyle); - return Promise.all(cmds); -} - -async function run(files) { - try { - await buildStyles(files); - } catch (error) { - console.error(error); - process.exit(1); - } -} - -const args = process.argv.slice(2); - -if (args.includes('-w') || args.includes('--watch')) { - console.log(`Watching ${files.length} scss files in: ${root}`); - const watcher = chokidar.watch(files); - watcher - .on('add', (path) => { - console.log(`Compiling sass: ${path}`); - buildStyles([path]); - }) - .on('change', (path) => { - console.log(`Compiling sass: ${path}`); - buildStyles([path]); - }); -} else { - run(files); -} diff --git a/scripts/transform-scss.js b/scripts/transform-scss.js deleted file mode 100644 index af8c936b..00000000 --- a/scripts/transform-scss.js +++ /dev/null @@ -1,40 +0,0 @@ -const fs = require('fs'); -const glob = require('glob'); - -const root = `${process.cwd()}`; - -async function transformFiles() { - const esmRoot = `${root}/dist/**/*.js`; - const files = glob.sync(esmRoot).filter((path) => !path.includes('/src/')); - const cmds = files.map((file) => { - let content = fs.readFileSync(file, { encoding: 'utf-8' }); - const isEsm = file.includes('/esm/'); - if (isEsm) { - /** - * For ESM module, tranform the CSS asset paht co CJS variant. - * Referencing CSS in esm directories causes webpack to tree shake the assets leading to missing CSS rules in build output. - */ - const prefix = file.split('/esm/').pop().split('/').shift(); - content = content.replaceAll(/(?<=^import )'\.\/(?=.*\.scss)/gm, `'../${prefix}/`); - } - content = content.replace(/\.scss(?=('))/, '.css'); - content = content.replace(/\.scss(?=("\)))/, '.css'); - return fs.writeFile(file, content, 'utf-8', function (err) { - if (err) { - throw err; - } - }); - }); - return Promise.all(cmds); -} - -async function run() { - try { - await transformFiles(); - } catch (error) { - console.error(error); - process.exit(1); - } -} - -run();