-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathindex.ts
More file actions
142 lines (119 loc) · 3.21 KB
/
index.ts
File metadata and controls
142 lines (119 loc) · 3.21 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
import type {
Animation_V2,
ReactNativeCssStyleSheet,
StyleRuleSet,
} from "react-native-css/compiler";
import { DEFAULT_CONTAINER_NAME } from "../runtime/native/conditions/container-query";
import {
family,
observable,
observableBatch,
type Observable,
} from "../runtime/native/reactivity";
import { rootVariables, universalVariables } from "./root";
export { rootVariables, universalVariables };
interface StyleCollectionType {
styles: ReturnType<typeof family<string, Observable<StyleRuleSet>>>;
keyframes: ReturnType<typeof family<string, Observable<Animation_V2[1]>>>;
inject: (options: ReactNativeCssStyleSheet) => void;
}
declare global {
var __react_native_css_style_collection: StyleCollectionType | undefined;
}
globalThis.__react_native_css_style_collection ??= {
styles: family<string, Observable<StyleRuleSet>>(() => {
return observable([], isDeepEqual);
}),
keyframes: family<string, Observable<Animation_V2[1]>>(() => {
return observable([], isDeepEqual);
}),
inject: function (options: ReactNativeCssStyleSheet) {
observableBatch.current = new Set();
StyleCollection.styles("will-change-variable").set([
{
s: [0],
v: [],
},
]);
StyleCollection.styles("will-change-container").set([
{
s: [0],
c: [DEFAULT_CONTAINER_NAME],
},
]);
StyleCollection.styles("will-change-animation").set([
{
s: [0],
a: true,
},
]);
StyleCollection.styles("will-change-pressable").set([
{
s: [0],
p: {
h: 1,
},
},
]);
if (options.s) {
for (const style of options.s) {
StyleCollection.styles(style[0]).set(style[1]);
}
}
if (options.k) {
for (const keyframes of options.k) {
StyleCollection.keyframes(keyframes[0]).set(keyframes[1]);
}
}
if (options.vr) {
for (const entry of options.vr) {
rootVariables(entry[0]).set(entry[1]);
}
}
if (options.vu) {
for (const entry of options.vu) {
rootVariables(entry[0]).set(entry[1]);
}
}
for (const effect of observableBatch.current) {
effect.run();
}
observableBatch.current = undefined;
},
};
export const StyleCollection = globalThis.__react_native_css_style_collection;
function isDeepEqual(a: unknown, b: unknown): boolean {
const aArray = Array.isArray(a);
const bArray = Array.isArray(b);
const requiresKeyComparison =
typeof a === "object" && typeof b === "object" && aArray === bArray;
// Only compare keys when both are an object or array
// This does not account for complex types like Date/Regex, because we don't use them
if (!requiresKeyComparison) return a === b;
// Make either are not null
if (!a || !b) {
return a === b;
}
// Shortcut for arrays
if (aArray && bArray && a.length !== b.length) {
return false;
}
// Compare a to b
for (const key in a) {
if (
!isDeepEqual(
(a as Record<string, unknown>)[key],
(b as Record<string, unknown>)[key],
)
) {
return false;
}
}
// Compare b to a
for (const key in b) {
if (!(key in a)) {
return false;
}
}
return true;
}