Skip to content

Commit

Permalink
Merge pull request #268 from Telegram-Mini-Apps/feature/better-classn…
Browse files Browse the repository at this point in the history
…ames

feat(utils): improve classNames
  • Loading branch information
heyqbnk authored Mar 27, 2024
2 parents 54d1133 + 1e43c94 commit 51bab4a
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-melons-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tma.js/sdk": patch
---

Better classNames util
4 changes: 4 additions & 0 deletions packages/sdk/src/classnames/__tests__/classNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ it('should ignore all non-empty strings and objects', () => {
expect(classNames('', 2, 'b', null, undefined, false, true, [], 'a', 'c')).toBe('b a c');
});

it('should apply classNames function to the item, if it is an array', () => {
expect(classNames(['a', 'b', 'c'])).toBe('a b c');
})

it('should pick only keys which values are truthy', () => {
expect(classNames({
a: true,
Expand Down
32 changes: 20 additions & 12 deletions packages/sdk/src/classnames/classNames.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
import { isRecord } from '../misc/isRecord.js';

/**
* Inserts a space between a and b in case both of them are
* non-empty strings.
* @param a
* @param b
*/
function space(a: string, b: string): string {
return a + (a.length > 0 && b.length > 0 ? ` ${b}` : b);
return a + (a.length && b.length ? ` ${b}` : b);
}

/**
* Function which joins passed values with space following these rules:
* 1. If value is non-empty string, it will be added to output.
* 2. If value is object, only those keys will be added, which values are truthy.
* 3. All other values are ignored.
* 3. If value is array, classNames will be called with this value spread.
* 4. All other values are ignored.
*
* You can find this function to similar one from package {@link https://www.npmjs.com/package/classnames|classnames}.
* You can find this function to similar one from the package {@link https://www.npmjs.com/package/classnames|classnames}.
* @param values - values array.
* @returns Final class name.
*/
export function classNames(...values: any[]): string {
return values.reduce<string>((acc, value) => {
let formattedValue = '';

return values.reduce((acc, value) => {
if (typeof value === 'string') {
formattedValue = value;
} else if (typeof value === 'object' && value !== null) {
formattedValue = Object
.entries(value)
.reduce<string>((valueAcc, [className, enable]) => (enable ? space(valueAcc, className) : valueAcc), '');
return space(acc, value);
}

if (isRecord(value)) {
return space(acc, Object.entries(value).reduce((valueAcc, entry) => {
return (entry[1] ? space(valueAcc, entry[0]) : valueAcc);
}, ''));
}

if (Array.isArray(value)) {
return space(acc, classNames(...value));
}

return space(acc, formattedValue);
return acc;
}, '');
}

0 comments on commit 51bab4a

Please sign in to comment.