/
utils.ts
90 lines (85 loc) · 2.15 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import { Text } from '@jupyterlab/coreutils';
/**
* Inner works of class combining functions
*/
function _classes(
classes: (string | false | undefined | null | { [className: string]: any })[]
): string[] {
return classes
.map(c =>
c && typeof c === 'object'
? Object.keys(c).map(key => !!c[key] && key)
: typeof c === 'string'
? c.split(/\s+/)
: []
)
.reduce((flattened, c) => flattened.concat(c), [] as string[])
.filter(c => !!c) as string[];
}
/**
* Combines classNames.
*
* @param classes - A list of classNames
*
* @returns A single string with the combined className
*/
export function classes(
...classes: (
| string
| false
| undefined
| null
| { [className: string]: any }
)[]
): string {
return _classes(classes).join(' ');
}
/**
* Combines classNames. Removes all duplicates
*
* @param classes - A list of classNames
*
* @returns A single string with the combined className
*/
export function classesDedupe(
...classes: (
| string
| false
| undefined
| null
| { [className: string]: any }
)[]
): string {
return [...new Set(_classes(classes))].join(' ');
}
/**
* Translates the attributes of a DOM element into attributes that can
* be understood by React. Currently not comprehensive, we will add special
* cases as they become relevant.
*
* @param elem - A DOM element
*
* @param ignore - An optional list of attribute names to ignore
*
* @returns An object with key:value pairs that are the React-friendly
* translation of elem's attributes
*/
export function getReactAttrs(
elem: Element,
{ ignore = [] }: { ignore?: string[] } = {}
): { [key: string]: string | null } {
return elem
.getAttributeNames()
.reduce<{ [key: string]: string | null }>((d, name) => {
if (name === 'style' || ignore.includes(name)) {
void 0;
} else if (name.startsWith('data')) {
d[name] = elem.getAttribute(name);
} else {
d[Text.camelCase(name)] = elem.getAttribute(name);
}
return d;
}, {});
}