-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathutils.ts
More file actions
189 lines (161 loc) · 4.92 KB
/
utils.ts
File metadata and controls
189 lines (161 loc) · 4.92 KB
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import { createElement, useCallback, useEffect, useState } from 'react';
import cl from 'classnames';
import {
Item,
type ItemElement,
type NormalizedItem,
} from '@deephaven/components';
import { dh as dhIcons } from '@deephaven/icons';
export const ISOLATED_SECTION_QUERY_CLASS = 'isolated-section-query';
export const SAMPLE_SECTION_CLASS = 'sample-section';
/**
* Generate a given number of `Item` elements.
*/
export function* generateItemElements(
start: number,
end: number
): Generator<ItemElement> {
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
const len = letters.length;
for (let i = start; i <= end; i += 1) {
const charI = i % len;
let suffix = String(Math.floor(i / len));
if (suffix === '0') {
suffix = '';
}
const letter = letters[charI];
const key = `${letter}${suffix}`;
const content = `${letter.repeat(3)}${suffix}`;
// eslint-disable-next-line react/no-children-prop
yield createElement(Item, {
key,
textValue: content,
children: content,
});
}
}
/**
* Generate a given number of NormalizedItems.
* @param count The number of items to generate
*/
export function* generateNormalizedItems(
count: number,
include: { descriptions?: boolean; icons?: boolean } = {}
): Generator<NormalizedItem> {
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
const len = letters.length;
const iconKeys = Object.keys(dhIcons);
for (let i = 0; i < count; i += 1) {
const charI = i % len;
let suffix = String(Math.floor(i / len));
if (suffix === '0') {
suffix = '';
}
const letter = letters[charI];
const key = `${letter}${suffix}`;
const icon =
include.icons === true ? iconKeys[i % iconKeys.length] : undefined;
const description =
include.descriptions === true ? `Description ${key}` : undefined;
const content = icon ?? `${letter.repeat(3)}${suffix}`;
yield {
key,
item: {
key: (i + 1) * 100,
content,
textValue: content,
description,
icon,
},
};
}
}
/**
* Pseudo random number generator with seed so we get reproducible output.
* This is necessary in order for e2e tests to work.
*/
export function* pseudoRandomWithSeed(
seed = 1
): Generator<number, void, never> {
while (true) {
// eslint-disable-next-line no-param-reassign
seed = (seed * 16807) % 2147483647;
yield seed / 2147483647;
}
}
/**
* If query string isolatedSection=true, return the current location hash.
* Otherwise ''
*/
function getIsolatedSectionHash() {
const isolateSection = window.location.search.includes('isolateSection=true');
return isolateSection ? window.location.hash.replace(/^#/, '') : '';
}
/**
* If query string isolatedSection=true, return the current location hash.
* Otherwise ''. Updates when the hash changes.
*/
export function useIsolateSectionHash(): string {
const [hash, setHash] = useState(getIsolatedSectionHash);
useEffect(() => {
const hashChangeHandler = () => setHash(getIsolatedSectionHash());
window.addEventListener('hashchange', hashChangeHandler);
return () => window.removeEventListener('hashchange', hashChangeHandler);
}, []);
return hash;
}
/**
* Returns a callback that will generate pseudo random numbers based on the
* given seed.
* @param seed
*/
export function useSeededRandomNumberCallback(seed = 1): () => number {
const [randomGenerator] = useState(() => pseudoRandomWithSeed(seed));
return useCallback(() => {
const result = randomGenerator.next();
if (result.done === true) {
throw new Error('Random number generator unexpectedly finished');
}
return result.value;
}, [randomGenerator]);
}
export function getSectionIdFromName(name: string): string {
return `${SAMPLE_SECTION_CLASS}-${name
.toLocaleLowerCase()
.replaceAll(' ', '-')}`;
}
/**
* Return id and className props for a sample section. Class
* names generated by this util are used by e2e tests to take snapshots of
* styleguide sections.
* @param name Name of the section
* @param classNames Optional list of class names to include
*/
export function sampleSectionIdAndClasses(
name: string,
classNames: string[] = []
): { id: string; className: string } {
const id = getSectionIdFromName(name);
const className = cl(SAMPLE_SECTION_CLASS, ...classNames);
return {
id,
className,
};
}
/**
* Return id and UNSAFE_className props for a sample section. Class
* names generated by this util are used by e2e tests to take snapshots of
* styleguide sections.
* @param name Name of the section
* @param classNames Optional list of class names to include
*/
export function sampleSectionIdAndClassesSpectrum(
name: string,
classNames: string[] = []
): { id: string; UNSAFE_className: string } {
const { id, className } = sampleSectionIdAndClasses(name, classNames);
return {
id,
UNSAFE_className: className,
};
}