@tamagui/static 3.0.0-beta.765.1 → 3.0.0-beta.804.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/dist/cjs/compiler.cjs +12 -1
- package/dist/cjs/compilerHost.cjs +642 -315
- package/dist/cjs/extractor/bundle.cjs +41 -17
- package/dist/cjs/extractor/getTamaguiConfigPathFromOptionsConfig.cjs +6 -1
- package/dist/cjs/extractor/loadTamagui.cjs +115 -64
- package/dist/esm/compiler.mjs +12 -1
- package/dist/esm/compiler.mjs.map +1 -1
- package/dist/esm/compilerHost.mjs +644 -316
- package/dist/esm/compilerHost.mjs.map +1 -1
- package/dist/esm/extractor/bundle.mjs +39 -16
- package/dist/esm/extractor/bundle.mjs.map +1 -1
- package/dist/esm/extractor/getTamaguiConfigPathFromOptionsConfig.mjs +6 -1
- package/dist/esm/extractor/getTamaguiConfigPathFromOptionsConfig.mjs.map +1 -1
- package/dist/esm/extractor/loadTamagui.mjs +115 -64
- package/dist/esm/extractor/loadTamagui.mjs.map +1 -1
- package/package.json +19 -19
- package/src/compiler.ts +16 -1
- package/src/compilerHost.ts +282 -93
- package/src/extractor/bundle.ts +7 -1
- package/src/extractor/getTamaguiConfigPathFromOptionsConfig.ts +9 -2
- package/types/compiler.d.ts.map +1 -1
- package/types/compilerHost.d.ts.map +1 -1
- package/types/extractor/bundle.d.ts.map +1 -1
- package/types/extractor/getTamaguiConfigPathFromOptionsConfig.d.ts.map +1 -1
package/src/compilerHost.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BranchDecisionNode,
|
|
2
3
|
CompilerLoweringHost,
|
|
3
4
|
CompilerTarget,
|
|
4
5
|
LoweringCandidateInput,
|
|
@@ -9,7 +10,11 @@ import type {
|
|
|
9
10
|
SourceEdit,
|
|
10
11
|
ZeroRule,
|
|
11
12
|
} from '@tamagui/compiler-core'
|
|
12
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
collectLeaves,
|
|
15
|
+
zeroRuleMessage,
|
|
16
|
+
zeroThemeBoundaryMessage,
|
|
17
|
+
} from '@tamagui/compiler-core'
|
|
13
18
|
import {
|
|
14
19
|
StyleObjectIdentifier,
|
|
15
20
|
StyleObjectProperty,
|
|
@@ -267,6 +272,29 @@ function extractedStyleArtifacts(
|
|
|
267
272
|
}
|
|
268
273
|
}
|
|
269
274
|
|
|
275
|
+
function spreadNonStyleReplacement(
|
|
276
|
+
form: MaterializedElement['form'],
|
|
277
|
+
entry: MaterializedElement['entries'][number],
|
|
278
|
+
isPropIgnored: (name: string) => boolean,
|
|
279
|
+
rewriteProp: (name: string, value: unknown) => [string, unknown]
|
|
280
|
+
): string {
|
|
281
|
+
if (
|
|
282
|
+
entry.kind !== 'spread' ||
|
|
283
|
+
entry.value.kind !== 'static' ||
|
|
284
|
+
!staticObject(entry.value.value)
|
|
285
|
+
) {
|
|
286
|
+
return ''
|
|
287
|
+
}
|
|
288
|
+
const nonStyleEntries = Object.entries(entry.value.value)
|
|
289
|
+
.filter(([key]) => !isPropIgnored(key))
|
|
290
|
+
.map(([key, value]) => rewriteProp(key, value))
|
|
291
|
+
if (nonStyleEntries.length === 0) return ''
|
|
292
|
+
const objectSource = `{ ${nonStyleEntries
|
|
293
|
+
.map(([key, value]) => `${JSON.stringify(key)}: ${JSON.stringify(value)}`)
|
|
294
|
+
.join(', ')} }`
|
|
295
|
+
return form === 'jsx' ? `{...${objectSource}}` : `...${objectSource}`
|
|
296
|
+
}
|
|
297
|
+
|
|
270
298
|
/**
|
|
271
299
|
* Granular edits inside a compiled-call props object. Whole-span replacement would
|
|
272
300
|
* also cover the children property, so nested candidates could never both commit.
|
|
@@ -274,7 +302,8 @@ function extractedStyleArtifacts(
|
|
|
274
302
|
function compiledPropsEdits(
|
|
275
303
|
input: LoweringCandidateInput,
|
|
276
304
|
styleEntries: MaterializedElement['entries'],
|
|
277
|
-
replacement: string
|
|
305
|
+
replacement: string,
|
|
306
|
+
spreadReplacement?: (entry: MaterializedElement['entries'][number]) => string
|
|
278
307
|
): SourceEdit[] | null {
|
|
279
308
|
const propsSpan = input.element.propsSpan
|
|
280
309
|
if (!propsSpan) return null
|
|
@@ -309,8 +338,10 @@ function compiledPropsEdits(
|
|
|
309
338
|
for (const [index, entry] of styleEntries.entries()) {
|
|
310
339
|
let start = entry.span.start
|
|
311
340
|
let end = entry.span.end
|
|
341
|
+
const nonStyle = spreadReplacement?.(entry) ?? ''
|
|
312
342
|
if (index === 0) {
|
|
313
|
-
|
|
343
|
+
const content = [replacement, nonStyle].filter(Boolean).join(', ')
|
|
344
|
+
edits.push({ start, end, content, origin: entry.span })
|
|
314
345
|
continue
|
|
315
346
|
}
|
|
316
347
|
|
|
@@ -323,7 +354,7 @@ function compiledPropsEdits(
|
|
|
323
354
|
while (cursor > 0 && /\s/.test(original[cursor]!)) cursor--
|
|
324
355
|
if (original[cursor] === ',') start = propsSpan.start + cursor
|
|
325
356
|
}
|
|
326
|
-
edits.push({ start, end, content:
|
|
357
|
+
edits.push({ start, end, content: nonStyle, origin: entry.span })
|
|
327
358
|
}
|
|
328
359
|
|
|
329
360
|
const merged: SourceEdit[] = []
|
|
@@ -1251,6 +1282,7 @@ export function createTamaguiCompilerHost(
|
|
|
1251
1282
|
}
|
|
1252
1283
|
process.env.TAMAGUI_TARGET = platform
|
|
1253
1284
|
try {
|
|
1285
|
+
core.prepareStyleStaticConfig(staticConfig)
|
|
1254
1286
|
return core.getSplitStyles(
|
|
1255
1287
|
props,
|
|
1256
1288
|
staticConfig,
|
|
@@ -1297,11 +1329,7 @@ export function createTamaguiCompilerHost(
|
|
|
1297
1329
|
if (!split) return null
|
|
1298
1330
|
|
|
1299
1331
|
const inlineStyle = split.viewProps?.style
|
|
1300
|
-
if (
|
|
1301
|
-
staticObject(inlineStyle) &&
|
|
1302
|
-
!inlineStyle['$$css'] &&
|
|
1303
|
-
Object.keys(inlineStyle).length > 0
|
|
1304
|
-
) {
|
|
1332
|
+
if (staticObject(inlineStyle) && Object.keys(inlineStyle).length > 0) {
|
|
1305
1333
|
return null
|
|
1306
1334
|
}
|
|
1307
1335
|
|
|
@@ -1643,8 +1671,11 @@ export function createTamaguiCompilerHost(
|
|
|
1643
1671
|
const namedAnimationDriver =
|
|
1644
1672
|
animatedBy === null ? null : options.tamaguiConfig.animationDrivers?.[animatedBy]
|
|
1645
1673
|
const namedCssAnimationDriver =
|
|
1646
|
-
platform === 'web' &&
|
|
1647
|
-
|
|
1674
|
+
platform === 'web' &&
|
|
1675
|
+
namedAnimationDriver &&
|
|
1676
|
+
!namedAnimationDriver.isStub &&
|
|
1677
|
+
namedAnimationDriver.outputStyle === 'css'
|
|
1678
|
+
? (namedAnimationDriver as AnimationDriver)
|
|
1648
1679
|
: null
|
|
1649
1680
|
const cssAnimationDriver =
|
|
1650
1681
|
namedCssAnimationDriver ??
|
|
@@ -1691,7 +1722,9 @@ export function createTamaguiCompilerHost(
|
|
|
1691
1722
|
!options.disablePartialExtraction &&
|
|
1692
1723
|
(input.element.form === 'jsx' || input.element.propsSpan !== null) &&
|
|
1693
1724
|
dynamicStyleEntries.length > 0 &&
|
|
1694
|
-
!input.element.entries.some(
|
|
1725
|
+
!input.element.entries.some(
|
|
1726
|
+
(entry) => entry.kind === 'spread' && entry.value.kind !== 'static'
|
|
1727
|
+
)
|
|
1695
1728
|
) {
|
|
1696
1729
|
const seen = new Set<string>()
|
|
1697
1730
|
const properties: string[] = []
|
|
@@ -1784,15 +1817,12 @@ export function createTamaguiCompilerHost(
|
|
|
1784
1817
|
// web per-branch conditional classes need the same preconditions the
|
|
1785
1818
|
// native per-branch path has, and take precedence over web partial
|
|
1786
1819
|
// extraction because a full flatten beats a runtime component
|
|
1787
|
-
// exactly one conditional: several would need a shared class
|
|
1788
|
-
// intersection across every branch combination, so elements with more
|
|
1789
|
-
// keep the web partial-extraction path they had before
|
|
1790
1820
|
const supportsWebConditionalClasses =
|
|
1791
1821
|
platform === 'web' &&
|
|
1792
1822
|
!options.disablePartialExtraction &&
|
|
1793
1823
|
(input.element.form === 'jsx' || input.element.propsSpan !== null) &&
|
|
1794
1824
|
dynamicHostStyleProperties === null &&
|
|
1795
|
-
dynamicStyleEntries.length
|
|
1825
|
+
dynamicStyleEntries.length > 0 &&
|
|
1796
1826
|
dynamicStyleEntries.every(
|
|
1797
1827
|
(entry) =>
|
|
1798
1828
|
entry.kind === 'prop' &&
|
|
@@ -1827,8 +1857,8 @@ export function createTamaguiCompilerHost(
|
|
|
1827
1857
|
asChildEntry?.span
|
|
1828
1858
|
)
|
|
1829
1859
|
}
|
|
1830
|
-
// group and
|
|
1831
|
-
// the group name, container writes '@' and '@name'. descendants read it
|
|
1860
|
+
// group and container props publish separate keys in the same context:
|
|
1861
|
+
// group writes the group name, container writes '@' and '@name'. descendants read it
|
|
1832
1862
|
// for `group-name-*` and `@name-*` clauses, so a flattened provider
|
|
1833
1863
|
// silently breaks every consumer under it. web compiles these to CSS
|
|
1834
1864
|
// container rules instead, so only native needs the bail.
|
|
@@ -1842,7 +1872,7 @@ export function createTamaguiCompilerHost(
|
|
|
1842
1872
|
return bailout(
|
|
1843
1873
|
input,
|
|
1844
1874
|
'local/unsupported-target',
|
|
1845
|
-
'Native group
|
|
1875
|
+
'Native group and container providers remain on the runtime path'
|
|
1846
1876
|
)
|
|
1847
1877
|
}
|
|
1848
1878
|
if (runtimeAnimationRequired && !cssAnimationDriver) {
|
|
@@ -1866,7 +1896,9 @@ export function createTamaguiCompilerHost(
|
|
|
1866
1896
|
!supportsWebConditionalClasses &&
|
|
1867
1897
|
component.partialRuntimeSafe
|
|
1868
1898
|
) {
|
|
1869
|
-
const hasSpread = input.element.entries.some(
|
|
1899
|
+
const hasSpread = input.element.entries.some(
|
|
1900
|
+
(entry) => entry.kind === 'spread' && entry.value.kind !== 'static'
|
|
1901
|
+
)
|
|
1870
1902
|
const unsupportedRuntimeStyle = input.element.entries.find(
|
|
1871
1903
|
(entry) =>
|
|
1872
1904
|
entry.kind === 'prop' &&
|
|
@@ -1922,7 +1954,6 @@ export function createTamaguiCompilerHost(
|
|
|
1922
1954
|
const partialInlineStyle = partialSplit?.viewProps?.style
|
|
1923
1955
|
const hasPartialInlineStyle =
|
|
1924
1956
|
staticObject(partialInlineStyle) &&
|
|
1925
|
-
!partialInlineStyle['$$css'] &&
|
|
1926
1957
|
Object.keys(partialInlineStyle).length > 0
|
|
1927
1958
|
if (partialSplit && !hasPartialInlineStyle) {
|
|
1928
1959
|
const artifacts = extractedStyleArtifacts(
|
|
@@ -2029,6 +2060,45 @@ export function createTamaguiCompilerHost(
|
|
|
2029
2060
|
props
|
|
2030
2061
|
)
|
|
2031
2062
|
}
|
|
2063
|
+
const propsForConditional = (
|
|
2064
|
+
target: Extract<MaterializedElement['entries'][number], { kind: 'prop' }>,
|
|
2065
|
+
value: unknown
|
|
2066
|
+
) => {
|
|
2067
|
+
const branchProps: Record<string, unknown> = {}
|
|
2068
|
+
for (const entry of input.element.entries) {
|
|
2069
|
+
if (entry === target) {
|
|
2070
|
+
branchProps[target.name] = value
|
|
2071
|
+
continue
|
|
2072
|
+
}
|
|
2073
|
+
if (entry.kind === 'child' || entry.value.kind !== 'static') continue
|
|
2074
|
+
if (entry.kind === 'spread') {
|
|
2075
|
+
if (staticObject(entry.value.value))
|
|
2076
|
+
Object.assign(branchProps, entry.value.value)
|
|
2077
|
+
} else {
|
|
2078
|
+
branchProps[entry.name] = entry.value.value
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
if (component.domTag && branchProps.hidden) branchProps.display = 'none'
|
|
2082
|
+
if (resolvedCssTransition !== null) {
|
|
2083
|
+
branchProps.transition = resolvedCssTransition
|
|
2084
|
+
}
|
|
2085
|
+
if (component.domTag && platform === 'native') {
|
|
2086
|
+
for (const [name, styleKey] of DOM_STYLE_ATTRIBUTES) {
|
|
2087
|
+
if (name in branchProps) {
|
|
2088
|
+
branchProps[styleKey] = branchProps[name]
|
|
2089
|
+
delete branchProps[name]
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
const branchCompleteProps =
|
|
2094
|
+
platform === 'native' && component.domTag && branchProps.display === 'flex'
|
|
2095
|
+
? core.mergeProps(
|
|
2096
|
+
core.mergeProps(defaultProps, NATIVE_FLEX_DEFAULTS),
|
|
2097
|
+
branchProps
|
|
2098
|
+
)
|
|
2099
|
+
: core.mergeProps(defaultProps, branchProps)
|
|
2100
|
+
return { branchProps, branchCompleteProps }
|
|
2101
|
+
}
|
|
2032
2102
|
// Against completeProps, not props: clauses also arrive from styled()
|
|
2033
2103
|
// defaults. Native resolution evaluates them against the build machine's
|
|
2034
2104
|
// current state, so folding would freeze that state into the bundle.
|
|
@@ -2130,6 +2200,22 @@ export function createTamaguiCompilerHost(
|
|
|
2130
2200
|
origin: span,
|
|
2131
2201
|
}))
|
|
2132
2202
|
|
|
2203
|
+
const isPropIgnored = (name: string) =>
|
|
2204
|
+
isStyleProp(name, component) || isInvalidHostStyleProp(name, component)
|
|
2205
|
+
const spreadReplacement = (
|
|
2206
|
+
form: MaterializedElement['form'],
|
|
2207
|
+
entry: MaterializedElement['entries'][number]
|
|
2208
|
+
) =>
|
|
2209
|
+
spreadNonStyleReplacement(form, entry, isPropIgnored, (name, value) => {
|
|
2210
|
+
if (platform !== 'web') return [name, value]
|
|
2211
|
+
if (name === 'testID') return ['data-testid', value]
|
|
2212
|
+
if (component.domTag && name === 'for') return ['htmlFor', value]
|
|
2213
|
+
if (component.domTag && name === 'role' && value === 'none') {
|
|
2214
|
+
return ['role', 'presentation']
|
|
2215
|
+
}
|
|
2216
|
+
return [name, value]
|
|
2217
|
+
})
|
|
2218
|
+
|
|
2133
2219
|
let styleEntries = input.element.entries.filter(
|
|
2134
2220
|
(entry) =>
|
|
2135
2221
|
(entry.kind === 'prop' &&
|
|
@@ -2138,7 +2224,7 @@ export function createTamaguiCompilerHost(
|
|
|
2138
2224
|
(entry.kind === 'spread' &&
|
|
2139
2225
|
entry.value.kind === 'static' &&
|
|
2140
2226
|
staticObject(entry.value.value) &&
|
|
2141
|
-
Object.keys(entry.value.value).
|
|
2227
|
+
Object.keys(entry.value.value).some(
|
|
2142
2228
|
(name) =>
|
|
2143
2229
|
isStyleProp(name, component) || isInvalidHostStyleProp(name, component)
|
|
2144
2230
|
))
|
|
@@ -2176,6 +2262,23 @@ export function createTamaguiCompilerHost(
|
|
|
2176
2262
|
invalidHostStyle.entry.span
|
|
2177
2263
|
)
|
|
2178
2264
|
}
|
|
2265
|
+
if (platform === 'native' && component.domTag) {
|
|
2266
|
+
const mixedSpread = styleEntries.find(
|
|
2267
|
+
(entry) =>
|
|
2268
|
+
entry.kind === 'spread' &&
|
|
2269
|
+
entry.value.kind === 'static' &&
|
|
2270
|
+
staticObject(entry.value.value) &&
|
|
2271
|
+
Object.keys(entry.value.value).some((name) => !isPropIgnored(name))
|
|
2272
|
+
)
|
|
2273
|
+
if (mixedSpread) {
|
|
2274
|
+
return bailout(
|
|
2275
|
+
input,
|
|
2276
|
+
'local/unsafe-style-spread',
|
|
2277
|
+
'Native DOM prop mapping requires non-style spread props to remain on the runtime path',
|
|
2278
|
+
mixedSpread.span
|
|
2279
|
+
)
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2179
2282
|
const webPropEdits: SourceEdit[] =
|
|
2180
2283
|
platform === 'web'
|
|
2181
2284
|
? input.element.entries.flatMap((entry) => {
|
|
@@ -2203,22 +2306,6 @@ export function createTamaguiCompilerHost(
|
|
|
2203
2306
|
? webDOMProps(input, component.domTag)
|
|
2204
2307
|
: { edits: [] as SourceEdit[], additions: [] as [string, string][] }
|
|
2205
2308
|
webPropEdits.push(...webDOMResult.edits)
|
|
2206
|
-
const unsafeSpread = input.element.entries.find(
|
|
2207
|
-
(entry) =>
|
|
2208
|
-
entry.kind === 'spread' &&
|
|
2209
|
-
!styleEntries.includes(entry) &&
|
|
2210
|
-
entry.value.kind === 'static' &&
|
|
2211
|
-
staticObject(entry.value.value) &&
|
|
2212
|
-
Object.keys(entry.value.value).some((name) => isStyleProp(name, component))
|
|
2213
|
-
)
|
|
2214
|
-
if (unsafeSpread) {
|
|
2215
|
-
return bailout(
|
|
2216
|
-
input,
|
|
2217
|
-
'local/unsafe-style-spread',
|
|
2218
|
-
'A mixed style/non-style spread cannot be removed transactionally',
|
|
2219
|
-
unsafeSpread.span
|
|
2220
|
-
)
|
|
2221
|
-
}
|
|
2222
2309
|
|
|
2223
2310
|
if (platform === 'native') {
|
|
2224
2311
|
const nativeStyleResolved = split.viewProps?.style
|
|
@@ -2498,6 +2585,8 @@ export function createTamaguiCompilerHost(
|
|
|
2498
2585
|
})
|
|
2499
2586
|
}
|
|
2500
2587
|
}
|
|
2588
|
+
const [first, ...rest] = styleEntries
|
|
2589
|
+
const firstNonStyle = first ? spreadReplacement('jsx', first) : ''
|
|
2501
2590
|
const propsEdits =
|
|
2502
2591
|
input.element.form === 'jsx'
|
|
2503
2592
|
? styleEntries.length === 0
|
|
@@ -2511,19 +2600,21 @@ export function createTamaguiCompilerHost(
|
|
|
2511
2600
|
]
|
|
2512
2601
|
: [
|
|
2513
2602
|
{
|
|
2514
|
-
start:
|
|
2515
|
-
end:
|
|
2516
|
-
content: propertyContent,
|
|
2517
|
-
origin:
|
|
2603
|
+
start: first!.span.start,
|
|
2604
|
+
end: first!.span.end,
|
|
2605
|
+
content: [propertyContent, firstNonStyle].filter(Boolean).join(' '),
|
|
2606
|
+
origin: first!.span,
|
|
2518
2607
|
},
|
|
2519
|
-
...
|
|
2608
|
+
...rest.map((entry) => ({
|
|
2520
2609
|
start: entry.span.start,
|
|
2521
2610
|
end: entry.span.end,
|
|
2522
|
-
content: '',
|
|
2611
|
+
content: spreadReplacement('jsx', entry),
|
|
2523
2612
|
origin: entry.span,
|
|
2524
2613
|
})),
|
|
2525
2614
|
]
|
|
2526
|
-
: compiledPropsEdits(input, styleEntries, propertyContent)
|
|
2615
|
+
: compiledPropsEdits(input, styleEntries, propertyContent, (entry) =>
|
|
2616
|
+
spreadReplacement(input.element.form, entry)
|
|
2617
|
+
)
|
|
2527
2618
|
if (!propsEdits) {
|
|
2528
2619
|
return bailout(
|
|
2529
2620
|
input,
|
|
@@ -2654,15 +2745,21 @@ export function createTamaguiCompilerHost(
|
|
|
2654
2745
|
entry.value.kind === 'conditional' &&
|
|
2655
2746
|
directStyleName(entry.name, component) !== 'opacity'
|
|
2656
2747
|
) {
|
|
2657
|
-
const
|
|
2658
|
-
|
|
2748
|
+
const tree = entry.value.tree
|
|
2749
|
+
const leaves = collectLeaves(tree)
|
|
2750
|
+
const leafDiffs = new Map<
|
|
2751
|
+
(typeof leaves)[number],
|
|
2752
|
+
Record<string, unknown>
|
|
2753
|
+
>()
|
|
2754
|
+
for (const leaf of leaves) {
|
|
2755
|
+
const { branchCompleteProps } = propsForConditional(entry, leaf.value)
|
|
2659
2756
|
const branchSplit = resolveSplitStyles(
|
|
2660
|
-
|
|
2757
|
+
branchCompleteProps,
|
|
2661
2758
|
component.staticConfig,
|
|
2662
2759
|
cssAnimationDriver,
|
|
2663
2760
|
component.displayName
|
|
2664
2761
|
)
|
|
2665
|
-
const branchStyle = branchSplit?.viewProps?.style
|
|
2762
|
+
const branchStyle = branchSplit?.viewProps?.style ?? {}
|
|
2666
2763
|
if (!staticObject(branchStyle)) {
|
|
2667
2764
|
return bailout(
|
|
2668
2765
|
input,
|
|
@@ -2728,18 +2825,23 @@ export function createTamaguiCompilerHost(
|
|
|
2728
2825
|
)
|
|
2729
2826
|
}
|
|
2730
2827
|
}
|
|
2731
|
-
|
|
2828
|
+
leafDiffs.set(leaf, diff)
|
|
2732
2829
|
}
|
|
2733
|
-
for (const diff of
|
|
2830
|
+
for (const diff of leafDiffs.values()) {
|
|
2734
2831
|
for (const key of Object.keys(diff)) conditionalKeys.add(key)
|
|
2735
2832
|
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2833
|
+
|
|
2834
|
+
function serializeNativeTree(node: BranchDecisionNode): string {
|
|
2835
|
+
if (node.kind === 'leaf') {
|
|
2836
|
+
const diff = leafDiffs.get(node) ?? {}
|
|
2837
|
+
return JSON.stringify(diff)
|
|
2838
|
+
}
|
|
2839
|
+
const index = expressions.length
|
|
2840
|
+
expressions.push(input.source.slice(node.test.start, node.test.end))
|
|
2841
|
+
return `expressions[${index}] ? ${serializeNativeTree(node.whenTrue)} : ${serializeNativeTree(node.whenFalse)}`
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
conditionalParts.push(serializeNativeTree(tree))
|
|
2743
2845
|
} else {
|
|
2744
2846
|
const index = expressions.length
|
|
2745
2847
|
expressions.push(
|
|
@@ -2780,6 +2882,7 @@ export function createTamaguiCompilerHost(
|
|
|
2780
2882
|
origin: span,
|
|
2781
2883
|
}))
|
|
2782
2884
|
const [first, ...rest] = styleEntries
|
|
2885
|
+
const firstNonStyle = first ? spreadReplacement('jsx', first) : ''
|
|
2783
2886
|
const expressionEdits =
|
|
2784
2887
|
styleEntries.length === 0
|
|
2785
2888
|
? []
|
|
@@ -2788,23 +2891,28 @@ export function createTamaguiCompilerHost(
|
|
|
2788
2891
|
{
|
|
2789
2892
|
start: first!.span.start,
|
|
2790
2893
|
end: first!.span.end,
|
|
2791
|
-
content:
|
|
2894
|
+
content: [
|
|
2792
2895
|
expressions.length > 0
|
|
2793
2896
|
? `_expressions={[${expressions.join(', ')}]}`
|
|
2794
2897
|
: '',
|
|
2898
|
+
firstNonStyle,
|
|
2899
|
+
]
|
|
2900
|
+
.filter(Boolean)
|
|
2901
|
+
.join(' '),
|
|
2795
2902
|
origin: first!.span,
|
|
2796
2903
|
},
|
|
2797
2904
|
...rest.map((entry) => ({
|
|
2798
2905
|
start: entry.span.start,
|
|
2799
2906
|
end: entry.span.end,
|
|
2800
|
-
content: '',
|
|
2907
|
+
content: spreadReplacement('jsx', entry),
|
|
2801
2908
|
origin: entry.span,
|
|
2802
2909
|
})),
|
|
2803
2910
|
]
|
|
2804
2911
|
: compiledPropsEdits(
|
|
2805
2912
|
input,
|
|
2806
2913
|
styleEntries,
|
|
2807
|
-
`_expressions: [${expressions.join(', ')}]
|
|
2914
|
+
`_expressions: [${expressions.join(', ')}]`,
|
|
2915
|
+
(entry) => spreadReplacement(input.element.form, entry)
|
|
2808
2916
|
)
|
|
2809
2917
|
if (!expressionEdits) {
|
|
2810
2918
|
return bailout(
|
|
@@ -2844,7 +2952,12 @@ export function createTamaguiCompilerHost(
|
|
|
2844
2952
|
origin: span,
|
|
2845
2953
|
}))
|
|
2846
2954
|
if (input.element.form !== 'jsx') {
|
|
2847
|
-
const propsEdits = compiledPropsEdits(
|
|
2955
|
+
const propsEdits = compiledPropsEdits(
|
|
2956
|
+
input,
|
|
2957
|
+
styleEntries,
|
|
2958
|
+
styleContent,
|
|
2959
|
+
(entry) => spreadReplacement(input.element.form, entry)
|
|
2960
|
+
)
|
|
2848
2961
|
if (!propsEdits) {
|
|
2849
2962
|
return bailout(
|
|
2850
2963
|
input,
|
|
@@ -2890,6 +3003,7 @@ export function createTamaguiCompilerHost(
|
|
|
2890
3003
|
}
|
|
2891
3004
|
}
|
|
2892
3005
|
const [first, ...rest] = styleEntries
|
|
3006
|
+
const firstNonStyle = first ? spreadReplacement('jsx', first) : ''
|
|
2893
3007
|
return {
|
|
2894
3008
|
ok: true,
|
|
2895
3009
|
edits: [
|
|
@@ -2898,13 +3012,15 @@ export function createTamaguiCompilerHost(
|
|
|
2898
3012
|
{
|
|
2899
3013
|
start: first!.span.start,
|
|
2900
3014
|
end: first!.span.end,
|
|
2901
|
-
content: `style={${nativeStyleSource}}`,
|
|
3015
|
+
content: [`style={${nativeStyleSource}}`, firstNonStyle]
|
|
3016
|
+
.filter(Boolean)
|
|
3017
|
+
.join(' '),
|
|
2902
3018
|
origin: first!.span,
|
|
2903
3019
|
},
|
|
2904
3020
|
...rest.map((entry) => ({
|
|
2905
3021
|
start: entry.span.start,
|
|
2906
3022
|
end: entry.span.end,
|
|
2907
|
-
content: '',
|
|
3023
|
+
content: spreadReplacement('jsx', entry),
|
|
2908
3024
|
origin: entry.span,
|
|
2909
3025
|
})),
|
|
2910
3026
|
],
|
|
@@ -2929,9 +3045,7 @@ export function createTamaguiCompilerHost(
|
|
|
2929
3045
|
const className = artifacts.className
|
|
2930
3046
|
const rawInlineStyle = split.viewProps?.style
|
|
2931
3047
|
const inlineStyle =
|
|
2932
|
-
staticObject(rawInlineStyle) &&
|
|
2933
|
-
!rawInlineStyle['$$css'] &&
|
|
2934
|
-
Object.keys(rawInlineStyle).length > 0
|
|
3048
|
+
staticObject(rawInlineStyle) && Object.keys(rawInlineStyle).length > 0
|
|
2935
3049
|
? (rawInlineStyle as Record<string, unknown>)
|
|
2936
3050
|
: null
|
|
2937
3051
|
if (rawInlineStyle && !inlineStyle && !isSerializableNativeStyle(rawInlineStyle)) {
|
|
@@ -2969,11 +3083,7 @@ export function createTamaguiCompilerHost(
|
|
|
2969
3083
|
)
|
|
2970
3084
|
}
|
|
2971
3085
|
const itemInline = itemSplit.viewProps?.style
|
|
2972
|
-
if (
|
|
2973
|
-
staticObject(itemInline) &&
|
|
2974
|
-
!itemInline['$$css'] &&
|
|
2975
|
-
Object.keys(itemInline).length > 0
|
|
2976
|
-
) {
|
|
3086
|
+
if (staticObject(itemInline) && Object.keys(itemInline).length > 0) {
|
|
2977
3087
|
return bailout(
|
|
2978
3088
|
input,
|
|
2979
3089
|
'local/unsupported-target',
|
|
@@ -3005,17 +3115,30 @@ export function createTamaguiCompilerHost(
|
|
|
3005
3115
|
// branch's remainder becomes one ternary className segment. v3's web
|
|
3006
3116
|
// font architecture makes this cheap: sizes are family-independent
|
|
3007
3117
|
// variables, so a conditional fontFamily flips only its font_* class.
|
|
3008
|
-
|
|
3118
|
+
const baseStaticClasses = new Set(className.split(' ').filter(Boolean))
|
|
3119
|
+
const staticClasses = new Set(baseStaticClasses)
|
|
3009
3120
|
const webConditionalCSS: string[] = []
|
|
3121
|
+
const webConditionalKeys = new Set<string>()
|
|
3010
3122
|
const webConditionalEntries = supportsWebConditionalClasses
|
|
3011
3123
|
? dynamicStyleEntries.filter((entry) => entry.value.kind === 'conditional')
|
|
3012
3124
|
: []
|
|
3013
3125
|
for (const entry of webConditionalEntries) {
|
|
3014
3126
|
if (entry.value.kind !== 'conditional') continue
|
|
3015
|
-
const
|
|
3016
|
-
|
|
3127
|
+
const tree = entry.value.tree
|
|
3128
|
+
const leaves = collectLeaves(tree)
|
|
3129
|
+
const leafArtifactsMap = new Map<
|
|
3130
|
+
(typeof leaves)[number],
|
|
3131
|
+
{ classes: string[]; css: string[] }
|
|
3132
|
+
>()
|
|
3133
|
+
const entryConditionalKeys = new Set<string>()
|
|
3134
|
+
|
|
3135
|
+
for (const leaf of leaves) {
|
|
3136
|
+
const { branchProps, branchCompleteProps } = propsForConditional(
|
|
3137
|
+
entry,
|
|
3138
|
+
leaf.value
|
|
3139
|
+
)
|
|
3017
3140
|
const branchSplit = resolveSplitStyles(
|
|
3018
|
-
|
|
3141
|
+
branchCompleteProps,
|
|
3019
3142
|
component.staticConfig,
|
|
3020
3143
|
cssAnimationDriver,
|
|
3021
3144
|
component.displayName
|
|
@@ -3045,33 +3168,94 @@ export function createTamaguiCompilerHost(
|
|
|
3045
3168
|
)
|
|
3046
3169
|
}
|
|
3047
3170
|
}
|
|
3171
|
+
const changedKeys = new Set<string>()
|
|
3172
|
+
for (const key of new Set([
|
|
3173
|
+
...Object.keys(branchSplit.classNames ?? {}),
|
|
3174
|
+
...Object.keys(split.classNames ?? {}),
|
|
3175
|
+
])) {
|
|
3176
|
+
if (
|
|
3177
|
+
JSON.stringify(branchSplit.classNames?.[key]) !==
|
|
3178
|
+
JSON.stringify(split.classNames?.[key])
|
|
3179
|
+
) {
|
|
3180
|
+
changedKeys.add(key)
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
const branchStyle = branchSplit.viewProps?.style
|
|
3184
|
+
const baseStyle = split.viewProps?.style
|
|
3185
|
+
if (staticObject(branchStyle) || staticObject(baseStyle)) {
|
|
3186
|
+
for (const key of new Set([
|
|
3187
|
+
...Object.keys(staticObject(branchStyle) ? branchStyle : {}),
|
|
3188
|
+
...Object.keys(staticObject(baseStyle) ? baseStyle : {}),
|
|
3189
|
+
])) {
|
|
3190
|
+
if (
|
|
3191
|
+
JSON.stringify(
|
|
3192
|
+
staticObject(branchStyle) ? branchStyle[key] : undefined
|
|
3193
|
+
) !== JSON.stringify(staticObject(baseStyle) ? baseStyle[key] : undefined)
|
|
3194
|
+
) {
|
|
3195
|
+
changedKeys.add(key)
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
for (const key of changedKeys) {
|
|
3200
|
+
if (webConditionalKeys.has(key)) {
|
|
3201
|
+
return bailout(
|
|
3202
|
+
input,
|
|
3203
|
+
'local/dynamic-style-value',
|
|
3204
|
+
`Multiple conditionals contribute ${key}; their interaction cannot be resolved per-branch`,
|
|
3205
|
+
entry.value.span
|
|
3206
|
+
)
|
|
3207
|
+
}
|
|
3208
|
+
entryConditionalKeys.add(key)
|
|
3209
|
+
}
|
|
3048
3210
|
const branchArtifacts = extractedStyleArtifacts(
|
|
3049
3211
|
branchSplit,
|
|
3050
|
-
|
|
3212
|
+
branchProps,
|
|
3051
3213
|
options.tamaguiConfig,
|
|
3052
3214
|
!component.domTag,
|
|
3053
3215
|
Boolean(component.staticConfig.styleFrontend)
|
|
3054
3216
|
)
|
|
3055
|
-
|
|
3217
|
+
leafArtifactsMap.set(leaf, {
|
|
3056
3218
|
classes: branchArtifacts.className.split(' ').filter(Boolean),
|
|
3057
3219
|
css: branchArtifacts.css,
|
|
3058
3220
|
})
|
|
3059
3221
|
}
|
|
3060
|
-
const
|
|
3061
|
-
|
|
3062
|
-
|
|
3222
|
+
for (const key of entryConditionalKeys) webConditionalKeys.add(key)
|
|
3223
|
+
|
|
3224
|
+
for (const artifacts of leafArtifactsMap.values()) {
|
|
3225
|
+
webConditionalCSS.push(...artifacts.css)
|
|
3226
|
+
}
|
|
3227
|
+
|
|
3228
|
+
const allLeafArtifacts = leaves.map((l) => leafArtifactsMap.get(l)!)
|
|
3229
|
+
const sharedInConditional = new Set(
|
|
3230
|
+
allLeafArtifacts[0]?.classes.filter((c) =>
|
|
3231
|
+
allLeafArtifacts.every((a) => a.classes.includes(c))
|
|
3232
|
+
) ?? []
|
|
3063
3233
|
)
|
|
3064
|
-
const
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
const test = input.source.slice(entry.value.test.start, entry.value.test.end)
|
|
3070
|
-
programClassSources.push(
|
|
3071
|
-
`(${test}) ? ${JSON.stringify(trueOnly.join(' '))} : ${JSON.stringify(falseOnly.join(' '))}`
|
|
3072
|
-
)
|
|
3234
|
+
for (const cls of baseStaticClasses) {
|
|
3235
|
+
if (!sharedInConditional.has(cls)) staticClasses.delete(cls)
|
|
3236
|
+
}
|
|
3237
|
+
for (const cls of sharedInConditional) {
|
|
3238
|
+
if (!baseStaticClasses.has(cls)) staticClasses.add(cls)
|
|
3073
3239
|
}
|
|
3240
|
+
|
|
3241
|
+
function serializeWebTree(node: BranchDecisionNode): string {
|
|
3242
|
+
if (node.kind === 'leaf') {
|
|
3243
|
+
const artifacts = leafArtifactsMap.get(node)
|
|
3244
|
+
const only = artifacts
|
|
3245
|
+
? artifacts.classes.filter((item) => !sharedInConditional.has(item))
|
|
3246
|
+
: []
|
|
3247
|
+
return JSON.stringify(only.join(' '))
|
|
3248
|
+
}
|
|
3249
|
+
const test = input.source.slice(node.test.start, node.test.end)
|
|
3250
|
+
const truePart = serializeWebTree(node.whenTrue)
|
|
3251
|
+
const falsePart = serializeWebTree(node.whenFalse)
|
|
3252
|
+
return `(${test}) ? ${truePart} : ${falsePart}`
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3255
|
+
const classExpr = serializeWebTree(tree)
|
|
3256
|
+
programClassSources.push(classExpr)
|
|
3074
3257
|
}
|
|
3258
|
+
const webClassName = [...staticClasses].join(' ')
|
|
3075
3259
|
const hasStyleProgram = programClassSources.length > 0
|
|
3076
3260
|
const classNameExpression = hasStyleProgram
|
|
3077
3261
|
? `[${[JSON.stringify(webClassName), ...programClassSources].join(', ')}].filter(Boolean).join(" ")`
|
|
@@ -3104,7 +3288,9 @@ export function createTamaguiCompilerHost(
|
|
|
3104
3288
|
const webExtraProps = serializedProps(input.element.form, webDOMResult.additions)
|
|
3105
3289
|
if (input.element.form !== 'jsx') {
|
|
3106
3290
|
const replacement = [objectWebStyle, webExtraProps].filter(Boolean).join(', ')
|
|
3107
|
-
const propsEdits = compiledPropsEdits(input, styleEntries, replacement)
|
|
3291
|
+
const propsEdits = compiledPropsEdits(input, styleEntries, replacement, (entry) =>
|
|
3292
|
+
spreadReplacement(input.element.form, entry)
|
|
3293
|
+
)
|
|
3108
3294
|
if (!propsEdits) {
|
|
3109
3295
|
return bailout(
|
|
3110
3296
|
input,
|
|
@@ -3143,7 +3329,10 @@ export function createTamaguiCompilerHost(
|
|
|
3143
3329
|
}
|
|
3144
3330
|
|
|
3145
3331
|
const [first, ...rest] = styleEntries
|
|
3146
|
-
const
|
|
3332
|
+
const firstNonStyle = first ? spreadReplacement('jsx', first) : ''
|
|
3333
|
+
const attributes = [jsxWebStyle, webExtraProps, firstNonStyle]
|
|
3334
|
+
.filter(Boolean)
|
|
3335
|
+
.join(' ')
|
|
3147
3336
|
return {
|
|
3148
3337
|
ok: true,
|
|
3149
3338
|
edits: [
|
|
@@ -3158,7 +3347,7 @@ export function createTamaguiCompilerHost(
|
|
|
3158
3347
|
...rest.map((entry) => ({
|
|
3159
3348
|
start: entry.span.start,
|
|
3160
3349
|
end: entry.span.end,
|
|
3161
|
-
content: '',
|
|
3350
|
+
content: spreadReplacement('jsx', entry),
|
|
3162
3351
|
origin: entry.span,
|
|
3163
3352
|
})),
|
|
3164
3353
|
],
|