@niibase/uniwind 1.5.0 → 1.5.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/CHANGELOG.md +1173 -0
- package/dist/common/components/web/ActivityIndicator.js +3 -1
- package/dist/common/components/web/Button.js +3 -1
- package/dist/common/components/web/FlatList.js +3 -1
- package/dist/common/components/web/Image.js +3 -1
- package/dist/common/components/web/ImageBackground.js +3 -1
- package/dist/common/components/web/KeyboardAvoidingView.js +3 -1
- package/dist/common/components/web/Modal.js +3 -1
- package/dist/common/components/web/Pressable.js +3 -1
- package/dist/common/components/web/RefreshControl.js +3 -1
- package/dist/common/components/web/SafeAreaView.js +3 -1
- package/dist/common/components/web/ScrollView.js +3 -1
- package/dist/common/components/web/SectionList.js +3 -1
- package/dist/common/components/web/Switch.js +3 -1
- package/dist/common/components/web/Text.js +3 -1
- package/dist/common/components/web/TextInput.js +3 -1
- package/dist/common/components/web/TouchableHighlight.js +3 -1
- package/dist/common/components/web/TouchableOpacity.js +3 -1
- package/dist/common/components/web/TouchableWithoutFeedback.js +3 -1
- package/dist/common/components/web/View.js +2 -0
- package/dist/common/components/web/VirtualizedList.js +3 -1
- package/dist/common/components/web/generateDataSet.js +18 -0
- package/dist/common/core/web/cssListener.js +58 -6
- package/dist/common/core/web/getWebStyles.js +20 -18
- package/dist/common/css/extraUtilities.js +19 -0
- package/dist/common/css/index.js +2 -3
- package/dist/common/css/insets.js +2 -2
- package/dist/common/css/overwrite.js +2 -2
- package/dist/common/css/variants.js +2 -2
- package/dist/metro/metro-transformer.cjs +1 -1
- package/dist/metro/metro-transformer.mjs +1 -1
- package/dist/module/components/web/ActivityIndicator.js +3 -1
- package/dist/module/components/web/Button.js +3 -1
- package/dist/module/components/web/FlatList.js +3 -1
- package/dist/module/components/web/Image.js +3 -1
- package/dist/module/components/web/ImageBackground.js +3 -1
- package/dist/module/components/web/KeyboardAvoidingView.js +3 -1
- package/dist/module/components/web/Modal.js +3 -1
- package/dist/module/components/web/Pressable.js +3 -1
- package/dist/module/components/web/RefreshControl.js +3 -1
- package/dist/module/components/web/SafeAreaView.js +3 -1
- package/dist/module/components/web/ScrollView.js +3 -1
- package/dist/module/components/web/SectionList.js +3 -1
- package/dist/module/components/web/Switch.js +3 -1
- package/dist/module/components/web/Text.js +3 -1
- package/dist/module/components/web/TextInput.js +3 -1
- package/dist/module/components/web/TouchableHighlight.js +3 -1
- package/dist/module/components/web/TouchableOpacity.js +3 -1
- package/dist/module/components/web/TouchableWithoutFeedback.js +3 -1
- package/dist/module/components/web/View.js +2 -0
- package/dist/module/components/web/VirtualizedList.js +3 -1
- package/dist/module/components/web/generateDataSet.d.ts +32 -0
- package/dist/module/components/web/generateDataSet.js +9 -0
- package/dist/module/core/web/cssListener.d.ts +6 -1
- package/dist/module/core/web/cssListener.js +58 -6
- package/dist/module/core/web/getWebStyles.js +21 -18
- package/dist/module/css/extraUtilities.d.ts +1 -0
- package/dist/module/css/extraUtilities.js +20 -0
- package/dist/module/css/index.js +8 -8
- package/dist/module/css/insets.d.ts +1 -1
- package/dist/module/css/insets.js +2 -1
- package/dist/module/css/overwrite.d.ts +1 -1
- package/dist/module/css/overwrite.js +1 -1
- package/dist/module/css/variants.d.ts +1 -1
- package/dist/module/css/variants.js +2 -1
- package/dist/shared/{uniwind.DTMo4epG.cjs → uniwind.BZyFsest.cjs} +28 -6
- package/dist/shared/{uniwind.BWb5KNML.mjs → uniwind.C-rHhHOg.mjs} +28 -6
- package/dist/vite/index.cjs +1 -1
- package/dist/vite/index.mjs +1 -1
- package/package.json +3 -1
- package/src/components/web/ActivityIndicator.tsx +2 -0
- package/src/components/web/Button.tsx +2 -0
- package/src/components/web/FlatList.tsx +2 -0
- package/src/components/web/Image.tsx +2 -0
- package/src/components/web/ImageBackground.tsx +2 -0
- package/src/components/web/KeyboardAvoidingView.tsx +2 -0
- package/src/components/web/Modal.tsx +2 -0
- package/src/components/web/Pressable.tsx +2 -0
- package/src/components/web/RefreshControl.tsx +2 -0
- package/src/components/web/SafeAreaView.tsx +2 -0
- package/src/components/web/ScrollView.tsx +2 -0
- package/src/components/web/SectionList.tsx +2 -0
- package/src/components/web/Switch.tsx +2 -0
- package/src/components/web/Text.tsx +2 -0
- package/src/components/web/TextInput.tsx +2 -0
- package/src/components/web/TouchableHighlight.tsx +2 -0
- package/src/components/web/TouchableOpacity.tsx +2 -0
- package/src/components/web/TouchableWithoutFeedback.tsx +2 -0
- package/src/components/web/View.tsx +2 -0
- package/src/components/web/VirtualizedList.tsx +2 -0
- package/src/components/web/generateDataSet.ts +52 -0
- package/src/core/web/cssListener.ts +73 -6
- package/src/core/web/getWebStyles.ts +26 -25
- package/src/css/extraUtilities.ts +26 -0
- package/src/css/index.ts +8 -8
- package/src/css/insets.ts +3 -1
- package/src/css/overwrite.ts +1 -1
- package/src/css/variants.ts +3 -1
- package/uniwind.css +8 -0
|
@@ -2,9 +2,10 @@ import { StyleDependency } from '../../types'
|
|
|
2
2
|
import { UniwindListener } from '../listener'
|
|
3
3
|
|
|
4
4
|
class CSSListenerBuilder {
|
|
5
|
+
activeRules = new Set<CSSStyleRule>()
|
|
5
6
|
private classNameMediaQueryListeners = new Map<string, MediaQueryList>()
|
|
6
7
|
private listeners = new Map<MediaQueryList, Set<VoidFunction>>()
|
|
7
|
-
private
|
|
8
|
+
private registeredRulesMediaQueries = new Map<string, MediaQueryList>()
|
|
8
9
|
private processedStyleSheets = new WeakSet<CSSStyleSheet>()
|
|
9
10
|
private pendingInitialization: number | undefined = undefined
|
|
10
11
|
|
|
@@ -15,6 +16,22 @@ class CSSListenerBuilder {
|
|
|
15
16
|
|
|
16
17
|
const observer = new MutationObserver(mutations => {
|
|
17
18
|
for (const mutation of mutations) {
|
|
19
|
+
if (mutation.type === 'attributes') {
|
|
20
|
+
const el = mutation.target as HTMLLinkElement | HTMLStyleElement
|
|
21
|
+
|
|
22
|
+
if (!('sheet' in el)) {
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const sheet = el.sheet
|
|
27
|
+
|
|
28
|
+
if (sheet) {
|
|
29
|
+
this.processedStyleSheets.delete(sheet)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.scheduleInitialization()
|
|
33
|
+
}
|
|
34
|
+
|
|
18
35
|
if (mutation.type === 'childList') {
|
|
19
36
|
this.scheduleInitialization()
|
|
20
37
|
}
|
|
@@ -83,8 +100,19 @@ class CSSListenerBuilder {
|
|
|
83
100
|
}
|
|
84
101
|
}
|
|
85
102
|
|
|
103
|
+
private pruneStaleRules() {
|
|
104
|
+
const activeSheets = new Set(Array.from(document.styleSheets))
|
|
105
|
+
|
|
106
|
+
for (const rule of this.activeRules) {
|
|
107
|
+
if (!rule.parentStyleSheet || !activeSheets.has(rule.parentStyleSheet)) {
|
|
108
|
+
this.activeRules.delete(rule)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
86
113
|
private initialize() {
|
|
87
114
|
this.pendingInitialization = undefined
|
|
115
|
+
this.pruneStaleRules()
|
|
88
116
|
|
|
89
117
|
for (const sheet of Array.from(document.styleSheets)) {
|
|
90
118
|
// Skip already processed stylesheets
|
|
@@ -121,6 +149,10 @@ class CSSListenerBuilder {
|
|
|
121
149
|
return rule.constructor.name === 'CSSMediaRule'
|
|
122
150
|
}
|
|
123
151
|
|
|
152
|
+
private isSupportsRule(rule: CSSRule): rule is CSSSupportsRule {
|
|
153
|
+
return rule.constructor.name === 'CSSSupportsRule'
|
|
154
|
+
}
|
|
155
|
+
|
|
124
156
|
private collectParentMediaQueries(rule: CSSRule, acc = [] as Array<CSSMediaRule>): Array<CSSMediaRule> {
|
|
125
157
|
const { parentRule } = rule
|
|
126
158
|
|
|
@@ -144,13 +176,25 @@ class CSSListenerBuilder {
|
|
|
144
176
|
if (this.isStyleRule(rule)) {
|
|
145
177
|
const mediaQueries = this.collectParentMediaQueries(rule)
|
|
146
178
|
|
|
179
|
+
this.activeRules.add(rule)
|
|
180
|
+
|
|
147
181
|
if (mediaQueries.length > 0) {
|
|
148
|
-
this.addMediaQuery(mediaQueries, rule
|
|
182
|
+
this.addMediaQuery(mediaQueries, rule)
|
|
149
183
|
}
|
|
150
184
|
|
|
151
185
|
continue
|
|
152
186
|
}
|
|
153
187
|
|
|
188
|
+
if (this.isSupportsRule(rule)) {
|
|
189
|
+
if (!CSS.supports(rule.conditionText)) {
|
|
190
|
+
continue
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.addMediaQueriesDeep(rule.cssRules)
|
|
194
|
+
|
|
195
|
+
continue
|
|
196
|
+
}
|
|
197
|
+
|
|
154
198
|
if ('cssRules' in rule && rule.cssRules instanceof CSSRuleList) {
|
|
155
199
|
this.addMediaQueriesDeep(rule.cssRules)
|
|
156
200
|
|
|
@@ -159,27 +203,50 @@ class CSSListenerBuilder {
|
|
|
159
203
|
}
|
|
160
204
|
}
|
|
161
205
|
|
|
162
|
-
private addMediaQuery(mediaQueries: Array<CSSMediaRule>,
|
|
206
|
+
private addMediaQuery(mediaQueries: Array<CSSMediaRule>, rule: CSSStyleRule) {
|
|
207
|
+
const className = rule.selectorText
|
|
163
208
|
const rules = mediaQueries.map(mediaQuery => mediaQuery.conditionText).sort().join(' and ')
|
|
164
209
|
const parsedClassName = className.replace('.', '').replace('\\', '')
|
|
165
|
-
const cachedMediaQueryList = this.
|
|
210
|
+
const cachedMediaQueryList = this.registeredRulesMediaQueries.get(rules)
|
|
166
211
|
|
|
167
212
|
if (cachedMediaQueryList) {
|
|
168
213
|
this.classNameMediaQueryListeners.set(parsedClassName, cachedMediaQueryList)
|
|
214
|
+
this.toggleRule(cachedMediaQueryList, rule)
|
|
215
|
+
|
|
216
|
+
cachedMediaQueryList.addEventListener('change', () => {
|
|
217
|
+
this.toggleRule(cachedMediaQueryList, rule)
|
|
218
|
+
})
|
|
169
219
|
|
|
170
220
|
return
|
|
171
221
|
}
|
|
172
222
|
|
|
173
223
|
const mediaQueryList = window.matchMedia(rules)
|
|
174
224
|
|
|
175
|
-
this.
|
|
225
|
+
this.toggleRule(mediaQueryList, rule)
|
|
226
|
+
this.registeredRulesMediaQueries.set(rules, mediaQueryList)
|
|
176
227
|
this.listeners.set(mediaQueryList, new Set())
|
|
177
228
|
this.classNameMediaQueryListeners.set(parsedClassName, mediaQueryList)
|
|
178
229
|
|
|
179
230
|
mediaQueryList.addEventListener('change', () => {
|
|
180
|
-
this.listeners.get(mediaQueryList)!.forEach(listener =>
|
|
231
|
+
this.listeners.get(mediaQueryList)!.forEach(listener => {
|
|
232
|
+
listener()
|
|
233
|
+
})
|
|
234
|
+
this.toggleRule(mediaQueryList, rule)
|
|
181
235
|
})
|
|
182
236
|
}
|
|
237
|
+
|
|
238
|
+
private isRuleLive(rule: CSSStyleRule) {
|
|
239
|
+
const sheet = rule.parentStyleSheet
|
|
240
|
+
return sheet !== null && Array.from(document.styleSheets).includes(sheet)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private toggleRule(mqList: MediaQueryList, rule: CSSStyleRule) {
|
|
244
|
+
if (mqList.matches && this.isRuleLive(rule)) {
|
|
245
|
+
this.activeRules.add(rule)
|
|
246
|
+
} else {
|
|
247
|
+
this.activeRules.delete(rule)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
183
250
|
}
|
|
184
251
|
|
|
185
252
|
export const CSSListener = new CSSListenerBuilder()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RNStyle, UniwindContextType } from '../types'
|
|
2
|
+
import { CSSListener } from './cssListener'
|
|
2
3
|
import { parseCSSValue } from './parseCSSValue'
|
|
3
4
|
|
|
4
5
|
const dummyParent = typeof document !== 'undefined'
|
|
@@ -15,40 +16,40 @@ if (dummyParent && dummy) {
|
|
|
15
16
|
dummyParent.appendChild(dummy)
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const getActiveStylesForClass = (className: string) => {
|
|
20
|
+
const extractedStyles = {} as Record<string, string>
|
|
21
|
+
|
|
19
22
|
if (!dummy) {
|
|
20
|
-
return
|
|
23
|
+
return extractedStyles
|
|
21
24
|
}
|
|
22
25
|
|
|
26
|
+
const classNames = className.split(/\s+/).filter(Boolean)
|
|
23
27
|
const computedStyles = window.getComputedStyle(dummy)
|
|
24
|
-
const styles = {} as CSSStyleDeclaration
|
|
25
|
-
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
27
|
-
for (let i = 0; i < computedStyles.length; i++) {
|
|
28
|
-
// Typescript is unable to infer it properly
|
|
29
|
-
const prop = computedStyles[i] as any
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
CSSListener.activeRules.forEach(rule => {
|
|
30
|
+
const selector = rule.selectorText
|
|
31
|
+
const mightMatch = classNames.some((cls) => selector.includes(`.${CSS.escape(cls)}`))
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const initialStyles = typeof document !== 'undefined'
|
|
38
|
-
? getComputedStyles()
|
|
39
|
-
: {} as CSSStyleDeclaration
|
|
40
|
-
|
|
41
|
-
const getObjectDifference = <T extends object>(obj1: T, obj2: T): T => {
|
|
42
|
-
const diff = {} as T
|
|
43
|
-
const keys = Object.keys(obj2) as Array<keyof T>
|
|
33
|
+
if (!mightMatch) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
44
36
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
// element.matches() throws errors if it sees pseudo-elements like ::before
|
|
38
|
+
// So we strip them out safely just for the matching test
|
|
39
|
+
const safeSelector = selector.replace(/::[a-z-]+/gi, '')
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
if (safeSelector !== '' && dummy.matches(safeSelector)) {
|
|
43
|
+
for (const propertyName of rule.style) {
|
|
44
|
+
extractedStyles[propertyName] = computedStyles.getPropertyValue(propertyName)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} catch {
|
|
48
|
+
// Failsafe for unparseable selectors
|
|
48
49
|
}
|
|
49
50
|
})
|
|
50
51
|
|
|
51
|
-
return
|
|
52
|
+
return extractedStyles
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export const getWebStyles = (className: string | undefined, uniwindContext: UniwindContextType): RNStyle => {
|
|
@@ -68,7 +69,7 @@ export const getWebStyles = (className: string | undefined, uniwindContext: Uniw
|
|
|
68
69
|
|
|
69
70
|
dummy.className = className
|
|
70
71
|
|
|
71
|
-
const computedStyles =
|
|
72
|
+
const computedStyles = getActiveStylesForClass(className)
|
|
72
73
|
|
|
73
74
|
return Object.fromEntries(
|
|
74
75
|
Object.entries(computedStyles)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RNStyle } from '../core/types'
|
|
2
|
+
|
|
3
|
+
const toKebabCase = (str: string) => str.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`)
|
|
4
|
+
|
|
5
|
+
const generateExtraUtilities = (map: Record<string, RNStyle>) => {
|
|
6
|
+
return Object.entries(map)
|
|
7
|
+
.map(([name, style]) =>
|
|
8
|
+
[
|
|
9
|
+
`@utility ${name} {`,
|
|
10
|
+
...Object.entries(style).map(([key, value]) => ` ${toKebabCase(key)}: ${value};`),
|
|
11
|
+
`}`,
|
|
12
|
+
'',
|
|
13
|
+
].join('\n')
|
|
14
|
+
).join('\n')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const EXTRA_UTILITIES_MAP = {
|
|
18
|
+
'border-continuous': {
|
|
19
|
+
borderCurve: 'continuous',
|
|
20
|
+
},
|
|
21
|
+
'border-circular': {
|
|
22
|
+
borderCurve: 'circular',
|
|
23
|
+
},
|
|
24
|
+
} satisfies Record<string, RNStyle>
|
|
25
|
+
|
|
26
|
+
export const EXTRA_UTILITIES_CSS = generateExtraUtilities(EXTRA_UTILITIES_MAP)
|
package/src/css/index.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'path'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { EXTRA_UTILITIES_CSS } from './extraUtilities'
|
|
4
|
+
import { INSETS_CSS } from './insets'
|
|
5
|
+
import { OVERWRITE_CSS } from './overwrite'
|
|
5
6
|
import { generateCSSForThemes } from './themes'
|
|
6
|
-
import {
|
|
7
|
+
import { VARIANTS_CSS } from './variants'
|
|
7
8
|
|
|
8
9
|
const dirname = typeof __dirname !== 'undefined' ? __dirname : import.meta.dirname
|
|
9
10
|
|
|
10
11
|
export const buildCSS = async (themes: Array<string>, input: string) => {
|
|
11
|
-
const variants = generateCSSForVariants()
|
|
12
|
-
const insets = generateCSSForInsets()
|
|
13
12
|
const themesCSS = await generateCSSForThemes(themes, input)
|
|
14
13
|
const cssFilePath = path.join(dirname, '../../uniwind.css')
|
|
15
14
|
const oldCSSFile = fs.existsSync(cssFilePath)
|
|
@@ -17,9 +16,10 @@ export const buildCSS = async (themes: Array<string>, input: string) => {
|
|
|
17
16
|
: ''
|
|
18
17
|
|
|
19
18
|
const newCssFile = [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
VARIANTS_CSS,
|
|
20
|
+
INSETS_CSS,
|
|
21
|
+
OVERWRITE_CSS,
|
|
22
|
+
EXTRA_UTILITIES_CSS,
|
|
23
23
|
themesCSS,
|
|
24
24
|
].join('\n')
|
|
25
25
|
|
package/src/css/insets.ts
CHANGED
|
@@ -9,7 +9,7 @@ type TypeName = (typeof types)[number]
|
|
|
9
9
|
type SafeAreaType = (typeof safeAreaTypes)[number]
|
|
10
10
|
type Inset = 'top' | 'bottom' | 'left' | 'right'
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const generateCSSForInsets = () => {
|
|
13
13
|
let css = `@utility h-screen-safe {
|
|
14
14
|
height: calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)));
|
|
15
15
|
}\n\n`
|
|
@@ -104,3 +104,5 @@ export const generateCSSForInsets = () => {
|
|
|
104
104
|
// Remove the last newline character
|
|
105
105
|
return css.slice(0, -1)
|
|
106
106
|
}
|
|
107
|
+
|
|
108
|
+
export const INSETS_CSS = generateCSSForInsets()
|
package/src/css/overwrite.ts
CHANGED
package/src/css/variants.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const variants = ['ios', 'android', 'web', 'native', 'tv', 'android-tv', 'apple-tv']
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const generateCSSForVariants = () => {
|
|
4
4
|
let css = ''
|
|
5
5
|
|
|
6
6
|
variants.forEach(variant => {
|
|
@@ -9,3 +9,5 @@ export const generateCSSForVariants = () => {
|
|
|
9
9
|
|
|
10
10
|
return css
|
|
11
11
|
}
|
|
12
|
+
|
|
13
|
+
export const VARIANTS_CSS = generateCSSForVariants()
|
package/uniwind.css
CHANGED