From ee7d7b5e06de9811cc50c41c011439603b01ea02 Mon Sep 17 00:00:00 2001 From: Eugene Abrosimov Date: Wed, 17 Jan 2024 16:50:44 +0500 Subject: [PATCH 1/7] feat(withClassNames): add hocs folder --- jest.config.js | 2 +- lerna.json | 8 +------- package.json | 1 + 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/jest.config.js b/jest.config.js index 9c7f8d3c..175e18f2 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,5 @@ module.exports = { - roots: ['/components', '/hooks', '/services'], + roots: ['/components', '/hocs', '/hooks', '/services'], setupFilesAfterEnv: ['/.jest/setup.ts'], transform: { '^.+\\.tsx?$': 'ts-jest' diff --git a/lerna.json b/lerna.json index 73d6f367..b640a922 100644 --- a/lerna.json +++ b/lerna.json @@ -1,11 +1,5 @@ { - "packages": [ - "components/*", - "hooks/*", - "packages/*", - "services/*", - "styles/*" - ], + "packages": ["components/*", "hocs/*", "hooks/*", "packages/*", "services/*", "styles/*"], "useWorkspaces": true, "version": "independent", "npmClient": "npm", diff --git a/package.json b/package.json index 0a79ca58..3670bb10 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "private": true, "workspaces": [ "components/*", + "hocs/*", "hooks/*", "packages/*", "services/*", From 8210bb96841509366c252f30c7d4960aefe0124b Mon Sep 17 00:00:00 2001 From: Eugene Abrosimov Date: Wed, 17 Jan 2024 17:04:19 +0500 Subject: [PATCH 2/7] feat(withClassNames): add package --- hocs/with-class-names/README.md | 11 ++++++++++ hocs/with-class-names/package.json | 32 +++++++++++++++++++++++++++++ hocs/with-class-names/tsconfig.json | 17 +++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 hocs/with-class-names/README.md create mode 100644 hocs/with-class-names/package.json create mode 100644 hocs/with-class-names/tsconfig.json diff --git a/hocs/with-class-names/README.md b/hocs/with-class-names/README.md new file mode 100644 index 00000000..4ba9f79b --- /dev/null +++ b/hocs/with-class-names/README.md @@ -0,0 +1,11 @@ +# `@byndyusoft-ui/with-class-names` + +--- + +> High Order Component for css styles injection ... + +### Installation + +``` +npm i @byndyusoft-ui/with-class-names +``` diff --git a/hocs/with-class-names/package.json b/hocs/with-class-names/package.json new file mode 100644 index 00000000..e9eec2e7 --- /dev/null +++ b/hocs/with-class-names/package.json @@ -0,0 +1,32 @@ +{ + "name": "@byndyusoft-ui/with-class-names", + "version": "0.0.0", + "description": "Byndyusoft UI React High Order Component for css styles injection", + "keywords": [ + "byndyusoft", + "byndyusoft-ui", + "react", + "hoc" + ], + "author": "Byndyusoft Frontend Stream ", + "homepage": "https://github.com/Byndyusoft/ui/tree/master/hocs/with-class-names#readme", + "license": "Apache-2.0", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/Byndyusoft/ui.git" + }, + "scripts": { + "build": "tsc", + "clean": "rimraf dist", + "lint": "eslint src --config ../../eslint.config.js", + "test": "jest --config ../../jest.config.js" + }, + "bugs": { + "url": "https://github.com/Byndyusoft/ui/issues" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/hocs/with-class-names/tsconfig.json b/hocs/with-class-names/tsconfig.json new file mode 100644 index 00000000..094a8f9a --- /dev/null +++ b/hocs/with-class-names/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "dist", + "outDir": "dist", + "module": "commonjs", + "target": "es6" + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "src/*.tests.ts" + ] +} From c6bf0b4a0260aff49f09286c2ec85f71c48f0098 Mon Sep 17 00:00:00 2001 From: Eugene Abrosimov Date: Wed, 17 Jan 2024 17:11:49 +0500 Subject: [PATCH 3/7] feat(withClassNames): add implementation --- hocs/with-class-names/src/index.ts | 1 + hocs/with-class-names/src/withClassNames.tsx | 7 +++++++ hocs/with-class-names/src/withClassNames.types.ts | 3 +++ 3 files changed, 11 insertions(+) create mode 100644 hocs/with-class-names/src/index.ts create mode 100644 hocs/with-class-names/src/withClassNames.tsx create mode 100644 hocs/with-class-names/src/withClassNames.types.ts diff --git a/hocs/with-class-names/src/index.ts b/hocs/with-class-names/src/index.ts new file mode 100644 index 00000000..e7d7dcdb --- /dev/null +++ b/hocs/with-class-names/src/index.ts @@ -0,0 +1 @@ +export { default } from './withClassNames'; diff --git a/hocs/with-class-names/src/withClassNames.tsx b/hocs/with-class-names/src/withClassNames.tsx new file mode 100644 index 00000000..5ce2d2b1 --- /dev/null +++ b/hocs/with-class-names/src/withClassNames.tsx @@ -0,0 +1,7 @@ +import React, { ComponentType, PropsWithChildren } from 'react'; +import { IClassNames } from './withClassNames.types'; + +export default function withClassNames(Component: ComponentType

>, classNames: CN) { + // eslint-disable-next-line react/display-name,@typescript-eslint/explicit-module-boundary-types + return (props: PropsWithChildren

) => ; +} diff --git a/hocs/with-class-names/src/withClassNames.types.ts b/hocs/with-class-names/src/withClassNames.types.ts new file mode 100644 index 00000000..c1f2b6c3 --- /dev/null +++ b/hocs/with-class-names/src/withClassNames.types.ts @@ -0,0 +1,3 @@ +export interface IClassNames { + classNames: CN; +} From 2691d4e79467fe8695f816a29d0764e3c51e0706 Mon Sep 17 00:00:00 2001 From: tolms Date: Tue, 23 Jan 2024 15:01:20 +0500 Subject: [PATCH 4/7] feat(withClassNames): package-lock.json changes --- package-lock.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/package-lock.json b/package-lock.json index 344ab9f4..9081093d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "license": "Apache-2.0", "workspaces": [ "components/*", + "hocs/*", "hooks/*", "packages/*", "services/*", @@ -67,6 +68,10 @@ "version": "0.1.0", "license": "ISC" }, + "hocs/with-class-names": { + "version": "0.0.0", + "license": "Apache-2.0" + }, "hooks/use-click-outside": { "name": "@byndyusoft-ui/use-click-outside", "version": "0.1.0", @@ -2166,6 +2171,10 @@ "resolved": "hooks/use-window-size", "link": true }, + "node_modules/@byndyusoft-ui/with-class-names": { + "resolved": "hocs/with-class-names", + "link": true + }, "node_modules/@byndyusoft/eslint-config": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@byndyusoft/eslint-config/-/eslint-config-2.0.0.tgz", @@ -34439,6 +34448,9 @@ "@byndyusoft-ui/use-latest-ref": "*" } }, + "@byndyusoft-ui/with-class-names": { + "version": "file:hocs/with-class-names" + }, "@byndyusoft/eslint-config": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@byndyusoft/eslint-config/-/eslint-config-2.0.0.tgz", From 1c94921bf3a517c9191b0ad5f34a10f1dcc8f82a Mon Sep 17 00:00:00 2001 From: tolms Date: Thu, 25 Jan 2024 19:26:24 +0500 Subject: [PATCH 5/7] feat(withClassNames): add method for merge classNames --- hocs/with-class-names/package.json | 2 +- hocs/with-class-names/src/index.ts | 2 + .../src/mergeClassNames.tests.ts | 23 ++++++++++++ hocs/with-class-names/src/mergeClassNames.ts | 37 +++++++++++++++++++ hocs/with-class-names/src/withClassNames.tsx | 16 ++++++-- .../src/withClassNames.types.ts | 3 -- 6 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 hocs/with-class-names/src/mergeClassNames.tests.ts create mode 100644 hocs/with-class-names/src/mergeClassNames.ts delete mode 100644 hocs/with-class-names/src/withClassNames.types.ts diff --git a/hocs/with-class-names/package.json b/hocs/with-class-names/package.json index e9eec2e7..a4731352 100644 --- a/hocs/with-class-names/package.json +++ b/hocs/with-class-names/package.json @@ -21,7 +21,7 @@ "build": "tsc", "clean": "rimraf dist", "lint": "eslint src --config ../../eslint.config.js", - "test": "jest --config ../../jest.config.js" + "test": "jest --config ../../jest.config.js --roots ./hocs/with-class-names/src" }, "bugs": { "url": "https://github.com/Byndyusoft/ui/issues" diff --git a/hocs/with-class-names/src/index.ts b/hocs/with-class-names/src/index.ts index e7d7dcdb..786cdaab 100644 --- a/hocs/with-class-names/src/index.ts +++ b/hocs/with-class-names/src/index.ts @@ -1 +1,3 @@ +export type { IClassNames, TClassNamesRecord } from './withClassNames'; +export { default as mergeClassNames } from './mergeClassNames'; export { default } from './withClassNames'; diff --git a/hocs/with-class-names/src/mergeClassNames.tests.ts b/hocs/with-class-names/src/mergeClassNames.tests.ts new file mode 100644 index 00000000..2fc07878 --- /dev/null +++ b/hocs/with-class-names/src/mergeClassNames.tests.ts @@ -0,0 +1,23 @@ +import mergeClassNames from './mergeClassNames'; + +describe('hocs / withClassNames / mergeClassNames', () => { + test('should return different classes', () => { + expect(mergeClassNames({}, { b: '2' })).toEqual({ b: '2' }); + expect(mergeClassNames({ a: '1' }, {})).toEqual({ a: '1' }); + expect(mergeClassNames({ a: '1' }, { b: '2' })).toEqual({ a: '1', b: '2' }); + }); + + test('should return replaced classes', () => { + expect(mergeClassNames({ a: '1' }, { a: '' })).toEqual({ a: '' }); + expect(mergeClassNames({ a: '1' }, { a: undefined })).toEqual({ a: undefined }); + expect(mergeClassNames({ a: '1' }, { a: '2', b: '3' })).toEqual({ a: '2', b: '3' }); + }); + + test('should return merged classes', () => { + expect(mergeClassNames({ a: '1', b: '3' }, { a: '2' }, { withReplace: false })).toEqual({ a: '1 2', b: '3' }); + expect(mergeClassNames({ a: '1', b: '' }, { a: '', b: '3' }, { withReplace: false })).toEqual({ + a: '1', + b: '3' + }); + }); +}); diff --git a/hocs/with-class-names/src/mergeClassNames.ts b/hocs/with-class-names/src/mergeClassNames.ts new file mode 100644 index 00000000..cfa64ccd --- /dev/null +++ b/hocs/with-class-names/src/mergeClassNames.ts @@ -0,0 +1,37 @@ +interface IMergeOptions { + withReplace?: boolean; +} + +const getDefaultOptions = (): IMergeOptions => ({ + withReplace: true +}); + +const joinClassNames = (target: CN, source: CN): CN => { + const result = Object.assign({}, target); + + for (const key in source) { + if (!source[key]) { + continue; + } + + if (result[key]) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + result[key] = [result[key], source[key]].join(' '); + } else { + result[key] = source[key]; + } + } + + return result; +}; + +export default function mergeClassNames(target: CN, source: CN, options: IMergeOptions = {}): CN { + const mergedOptions = Object.assign(getDefaultOptions(), options); + + if (mergedOptions.withReplace) { + return Object.assign({}, target, source); + } + + return joinClassNames(target, source); +} diff --git a/hocs/with-class-names/src/withClassNames.tsx b/hocs/with-class-names/src/withClassNames.tsx index 5ce2d2b1..f9f5b2d5 100644 --- a/hocs/with-class-names/src/withClassNames.tsx +++ b/hocs/with-class-names/src/withClassNames.tsx @@ -1,7 +1,15 @@ -import React, { ComponentType, PropsWithChildren } from 'react'; -import { IClassNames } from './withClassNames.types'; +import React, { ComponentType, FunctionComponent, PropsWithChildren } from 'react'; -export default function withClassNames(Component: ComponentType

>, classNames: CN) { - // eslint-disable-next-line react/display-name,@typescript-eslint/explicit-module-boundary-types +export interface IClassNames { + classNames?: CN; +} + +export type TClassNamesRecord = Partial>; + +export default function withClassNames( + Component: ComponentType

>, + classNames: CN +): FunctionComponent> { + // eslint-disable-next-line react/display-name return (props: PropsWithChildren

) => ; } diff --git a/hocs/with-class-names/src/withClassNames.types.ts b/hocs/with-class-names/src/withClassNames.types.ts deleted file mode 100644 index c1f2b6c3..00000000 --- a/hocs/with-class-names/src/withClassNames.types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface IClassNames { - classNames: CN; -} From f30497ab796c82450e1eaaeaff12a57a2ce52cb3 Mon Sep 17 00:00:00 2001 From: tolms Date: Thu, 25 Jan 2024 20:04:07 +0500 Subject: [PATCH 6/7] feat(withClassNames): add come docs --- hocs/with-class-names/README.md | 56 ++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/hocs/with-class-names/README.md b/hocs/with-class-names/README.md index 4ba9f79b..c5f7df8e 100644 --- a/hocs/with-class-names/README.md +++ b/hocs/with-class-names/README.md @@ -4,8 +4,62 @@ > High Order Component for css styles injection ... -### Installation +## Installation ``` npm i @byndyusoft-ui/with-class-names ``` + +## Method "mergeClassNames" +Use this method for merge component styles with custom styles +```ts + mergeClassNames(targetStyles, sourseStyles, options) +``` + +### Option "withReplace" ("true" by default) + + +## Usage example + +*Checkbox.tsx (Byndyusoft-UI component from "@byndyusoft-ui/Checkbox")* +```tsx + // ... Some imports + import { IClassNames, TClassNamesRecord } from '@byndyusoft-ui/with-class-names'; + import styles from './Checkbox.module.css'; + + // List of classNames for check TypeScript + const styleClassNames = ['container', 'disabled', 'input', 'field', 'label', 'trigger'] as const; + + export type TCheckboxClassNames = TClassNamesRecord<(typeof styleClassNames)[number]>; + export const checkboxClassNames = styles as TCheckboxClassNames; + +export interface ICheckboxProps extends InputHTMLAttributes, IClassNames { + // ... some props +} + +const Checkbox = forwardRef( + ( + { + classNames = checkboxClassNames, + // ... other props + }, + forwardedRef + ) => { + // ... component body + } +); +``` + +*Checkbox.tsx (Project component with custom styles)* +```tsx + import withClassNames, { mergeClassNames } from '@byndyusoft-ui/with-class-names'; + import Checkbox, { TCheckboxClassNames, checkboxClassNames } from '@byndyusoft-ui/Checkbox'; + import styles from './CheckboxWithReplacedStyles.module.css'; + + const Checkbox = withClassNames( + Checkbox, + mergeClassNames(checkboxClassNames, styles as TCheckboxClassNames) + ); + + export default Checkbox; +``` From 9d486aacfe1c2182477eef8e6ef0d1d0ad310b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=BE=D0=BB=D0=BC=D0=B0=D1=87=D0=B5=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B5=D1=80=D0=B3=D0=B5=D0=B9?= Date: Sat, 27 Jan 2024 13:15:27 +0500 Subject: [PATCH 7/7] Update hocs/with-class-names/README.md Co-authored-by: Dmitrii Maletskii <51035551+mltsk@users.noreply.github.com> --- hocs/with-class-names/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hocs/with-class-names/README.md b/hocs/with-class-names/README.md index c5f7df8e..5280da83 100644 --- a/hocs/with-class-names/README.md +++ b/hocs/with-class-names/README.md @@ -13,7 +13,7 @@ npm i @byndyusoft-ui/with-class-names ## Method "mergeClassNames" Use this method for merge component styles with custom styles ```ts - mergeClassNames(targetStyles, sourseStyles, options) + mergeClassNames(targetStyles, sourceStyles, options) ``` ### Option "withReplace" ("true" by default)