@octanejs/window 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +89 -0
- package/UPSTREAM.md +116 -0
- package/package.json +68 -0
- package/src/components/grid/Grid.tsx +329 -0
- package/src/components/grid/types.ts +334 -0
- package/src/components/grid/useGridCallbackRef.ts +16 -0
- package/src/components/grid/useGridRef.ts +12 -0
- package/src/components/list/List.tsx +216 -0
- package/src/components/list/isDynamicRowHeight.ts +10 -0
- package/src/components/list/types.ts +214 -0
- package/src/components/list/useDynamicRowHeight.ts +170 -0
- package/src/components/list/useListCallbackRef.ts +16 -0
- package/src/components/list/useListRef.ts +12 -0
- package/src/constants.ts +3 -0
- package/src/core/createCachedBounds.ts +65 -0
- package/src/core/getEstimatedSize.ts +25 -0
- package/src/core/getOffsetForIndex.ts +75 -0
- package/src/core/getStartStopIndices.ts +68 -0
- package/src/core/types.ts +14 -0
- package/src/core/useCachedBounds.ts +29 -0
- package/src/core/useIsRtl.ts +27 -0
- package/src/core/useItemSize.ts +33 -0
- package/src/core/useVirtualizer.ts +269 -0
- package/src/hooks/useIsomorphicLayoutEffect.ts +10 -0
- package/src/hooks/useMemoizedObject.ts +14 -0
- package/src/hooks/useResizeObserver.ts +98 -0
- package/src/hooks/useStableCallback.ts +39 -0
- package/src/index.ts +20 -0
- package/src/internal.ts +37 -0
- package/src/types.ts +5 -0
- package/src/utils/adjustScrollOffsetForRtl.ts +35 -0
- package/src/utils/areArraysEqual.ts +13 -0
- package/src/utils/arePropsEqual.ts +19 -0
- package/src/utils/assert.ts +10 -0
- package/src/utils/colors/getContrastColor.ts +47 -0
- package/src/utils/colors/stringToColor.ts +13 -0
- package/src/utils/debug.ts +13 -0
- package/src/utils/getRTLOffsetType.ts +46 -0
- package/src/utils/getScrollbarSize.ts +23 -0
- package/src/utils/isRtl.ts +12 -0
- package/src/utils/parseNumericStyleValue.ts +17 -0
- package/src/utils/shallowCompare.ts +26 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function stringToColor(string: string) {
|
|
2
|
+
let hash = 0;
|
|
3
|
+
string.split('').forEach((char) => {
|
|
4
|
+
hash = char.charCodeAt(0) + ((hash << 5) - hash);
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
let color = '#';
|
|
8
|
+
for (let i = 0; i < 3; i++) {
|
|
9
|
+
const value = (hash >> (i * 8)) & 0xff;
|
|
10
|
+
color += value.toString(16).padStart(2, '0');
|
|
11
|
+
}
|
|
12
|
+
return color;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getContrastColor } from './colors/getContrastColor.js';
|
|
2
|
+
import { stringToColor } from './colors/stringToColor.js';
|
|
3
|
+
|
|
4
|
+
export function debug(namespace: string, ...args: unknown[]) {
|
|
5
|
+
const backgroundColor = stringToColor(namespace);
|
|
6
|
+
const color = getContrastColor(backgroundColor);
|
|
7
|
+
|
|
8
|
+
console.log(
|
|
9
|
+
`%c ${namespace} `,
|
|
10
|
+
`background-color: ${backgroundColor}; color: ${color};`,
|
|
11
|
+
...args,
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type RTLOffsetType = 'negative' | 'positive-descending' | 'positive-ascending';
|
|
2
|
+
|
|
3
|
+
let cachedRTLResult: RTLOffsetType | null = null;
|
|
4
|
+
|
|
5
|
+
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
6
|
+
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
|
7
|
+
// Safari's elastic bounce makes detecting this even more complicated wrt potential false positives.
|
|
8
|
+
// The safest way to check this is to intentionally set a negative offset,
|
|
9
|
+
// and then verify that the subsequent "scroll" event matches the negative offset.
|
|
10
|
+
// If it does not match, then we can assume a non-standard RTL scroll implementation.
|
|
11
|
+
export function getRTLOffsetType(recalculate: boolean = false): RTLOffsetType {
|
|
12
|
+
if (cachedRTLResult === null || recalculate) {
|
|
13
|
+
const outerDiv = document.createElement('div');
|
|
14
|
+
const outerStyle = outerDiv.style;
|
|
15
|
+
outerStyle.width = '50px';
|
|
16
|
+
outerStyle.height = '50px';
|
|
17
|
+
outerStyle.overflow = 'scroll';
|
|
18
|
+
outerStyle.direction = 'rtl';
|
|
19
|
+
|
|
20
|
+
const innerDiv = document.createElement('div');
|
|
21
|
+
const innerStyle = innerDiv.style;
|
|
22
|
+
innerStyle.width = '100px';
|
|
23
|
+
innerStyle.height = '100px';
|
|
24
|
+
|
|
25
|
+
outerDiv.appendChild(innerDiv);
|
|
26
|
+
|
|
27
|
+
document.body.appendChild(outerDiv);
|
|
28
|
+
|
|
29
|
+
if (outerDiv.scrollLeft > 0) {
|
|
30
|
+
cachedRTLResult = 'positive-descending';
|
|
31
|
+
} else {
|
|
32
|
+
outerDiv.scrollLeft = 1;
|
|
33
|
+
if (outerDiv.scrollLeft === 0) {
|
|
34
|
+
cachedRTLResult = 'negative';
|
|
35
|
+
} else {
|
|
36
|
+
cachedRTLResult = 'positive-ascending';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
document.body.removeChild(outerDiv);
|
|
41
|
+
|
|
42
|
+
return cachedRTLResult;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return cachedRTLResult;
|
|
46
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
let size: number = -1;
|
|
2
|
+
|
|
3
|
+
export function getScrollbarSize(recalculate: boolean = false): number {
|
|
4
|
+
if (size === -1 || recalculate) {
|
|
5
|
+
const div = document.createElement('div');
|
|
6
|
+
const style = div.style;
|
|
7
|
+
style.width = '50px';
|
|
8
|
+
style.height = '50px';
|
|
9
|
+
style.overflow = 'scroll';
|
|
10
|
+
|
|
11
|
+
document.body.appendChild(div);
|
|
12
|
+
|
|
13
|
+
size = div.offsetWidth - div.clientWidth;
|
|
14
|
+
|
|
15
|
+
document.body.removeChild(div);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return size;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function setScrollbarSizeForTests(value: number) {
|
|
22
|
+
size = value;
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function isRtl(element: HTMLElement) {
|
|
2
|
+
let currentElement: HTMLElement | null = element;
|
|
3
|
+
while (currentElement) {
|
|
4
|
+
if (currentElement.dir) {
|
|
5
|
+
return currentElement.dir === 'rtl';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
currentElement = currentElement.parentElement;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
export function parseNumericStyleValue(value: CSSProperties['height']): number | undefined {
|
|
4
|
+
if (value !== undefined) {
|
|
5
|
+
switch (typeof value) {
|
|
6
|
+
case 'number': {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
case 'string': {
|
|
10
|
+
if (value.endsWith('px')) {
|
|
11
|
+
return parseFloat(value);
|
|
12
|
+
}
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { assert } from './assert.js';
|
|
2
|
+
|
|
3
|
+
export function shallowCompare<Type extends object>(a: Type | undefined, b: Type | undefined) {
|
|
4
|
+
if (a === b) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!!a !== !!b) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
assert(a !== undefined);
|
|
13
|
+
assert(b !== undefined);
|
|
14
|
+
|
|
15
|
+
if (Object.keys(a).length !== Object.keys(b).length) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
for (const key in a) {
|
|
20
|
+
if (!Object.is(b[key], a[key])) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return true;
|
|
26
|
+
}
|