@hanzogui/static 7.3.0 → 8.0.0

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.
Files changed (59) hide show
  1. package/dist/check-dep-versions.cjs +1 -1
  2. package/dist/checkDeps.cjs +10 -10
  3. package/dist/constants.cjs +2 -2
  4. package/dist/exports.cjs +2 -0
  5. package/dist/extractor/bundle.cjs +14 -4
  6. package/dist/extractor/bundleConfig.cjs +40 -27
  7. package/dist/extractor/concatClassName.cjs +40 -11
  8. package/dist/extractor/createExtractor.cjs +137 -30
  9. package/dist/extractor/extractHelpers.cjs +1 -1
  10. package/dist/extractor/extractMediaStyle.cjs +5 -5
  11. package/dist/extractor/extractToClassNames.cjs +52 -4
  12. package/dist/extractor/extractToNative.cjs +16 -8
  13. package/dist/extractor/getPrefixLogs.cjs +1 -1
  14. package/dist/extractor/getStaticBindingsForScope.cjs +2 -2
  15. package/dist/extractor/loadGui.cjs +52 -46
  16. package/dist/extractor/regenerateConfig.cjs +17 -17
  17. package/dist/extractor/watchGuiConfig.cjs +9 -9
  18. package/dist/getPragmaOptions.cjs +4 -4
  19. package/dist/registerRequire.cjs +17 -16
  20. package/package.json +22 -24
  21. package/src/check-dep-versions.ts +1 -1
  22. package/src/checkDeps.ts +25 -25
  23. package/src/constants.ts +2 -2
  24. package/src/exports.ts +1 -0
  25. package/src/extractor/bundle.ts +35 -6
  26. package/src/extractor/bundleConfig.ts +48 -28
  27. package/src/extractor/concatClassName.ts +37 -20
  28. package/src/extractor/createExtractor.ts +256 -36
  29. package/src/extractor/extractHelpers.ts +2 -2
  30. package/src/extractor/extractMediaStyle.ts +5 -5
  31. package/src/extractor/extractToClassNames.ts +109 -7
  32. package/src/extractor/extractToNative.ts +27 -10
  33. package/src/extractor/getPrefixLogs.ts +1 -1
  34. package/src/extractor/getStaticBindingsForScope.ts +2 -2
  35. package/src/extractor/loadGui.ts +66 -51
  36. package/src/extractor/regenerateConfig.ts +17 -17
  37. package/src/extractor/watchGuiConfig.ts +14 -9
  38. package/src/getPragmaOptions.ts +4 -4
  39. package/src/registerRequire.ts +32 -19
  40. package/types/constants.d.ts.map +1 -1
  41. package/types/exports.d.ts +1 -0
  42. package/types/exports.d.ts.map +1 -1
  43. package/types/extractor/bundle.d.ts.map +1 -1
  44. package/types/extractor/bundleConfig.d.ts +1 -1
  45. package/types/extractor/bundleConfig.d.ts.map +1 -1
  46. package/types/extractor/createExtractor.d.ts.map +1 -1
  47. package/types/extractor/extractMediaStyle.d.ts +1 -1
  48. package/types/extractor/extractMediaStyle.d.ts.map +1 -1
  49. package/types/extractor/extractToClassNames.d.ts.map +1 -1
  50. package/types/extractor/extractToNative.d.ts.map +1 -1
  51. package/types/extractor/loadGui.d.ts +5 -5
  52. package/types/extractor/loadGui.d.ts.map +1 -1
  53. package/types/extractor/regenerateConfig.d.ts +3 -3
  54. package/types/extractor/regenerateConfig.d.ts.map +1 -1
  55. package/types/extractor/watchGuiConfig.d.ts +1 -1
  56. package/types/extractor/watchGuiConfig.d.ts.map +1 -1
  57. package/types/registerRequire.d.ts +1 -1
  58. package/types/registerRequire.d.ts.map +1 -1
  59. package/LICENSE +0 -42
@@ -76,6 +76,43 @@ function isFullyDisabled(props: GuiOptions) {
76
76
  return props.disableExtraction && props.disableDebugAttr
77
77
  }
78
78
 
79
+ // Walk up JSX ancestors looking for one that declares `group="<groupName>"` together
80
+ // with the `untilMeasured` prop. Used to deopt children whose styles depend on a
81
+ // parent that the runtime measures before emitting child styles (can't be modeled
82
+ // in static CSS).
83
+ function hasUntilMeasuredAncestor(path: NodePath<any>, groupName: string): boolean {
84
+ let current: NodePath<any> | null = path.parentPath
85
+ while (current) {
86
+ if (current.isJSXElement()) {
87
+ const opening = current.node.openingElement
88
+ let foundGroup = false
89
+ let foundUntilMeasured = false
90
+ for (const attr of opening.attributes) {
91
+ if (!t.isJSXAttribute(attr)) continue
92
+ if (!t.isJSXIdentifier(attr.name)) continue
93
+ const aName = attr.name.name
94
+ if (aName === 'group') {
95
+ // only literal string equality counts — dynamic group= is left to runtime
96
+ if (t.isStringLiteral(attr.value) && attr.value.value === groupName) {
97
+ foundGroup = true
98
+ } else if (
99
+ t.isJSXExpressionContainer(attr.value) &&
100
+ t.isStringLiteral(attr.value.expression) &&
101
+ attr.value.expression.value === groupName
102
+ ) {
103
+ foundGroup = true
104
+ }
105
+ } else if (aName === 'untilMeasured') {
106
+ foundUntilMeasured = true
107
+ }
108
+ }
109
+ if (foundGroup && foundUntilMeasured) return true
110
+ }
111
+ current = current.parentPath
112
+ }
113
+ return false
114
+ }
115
+
79
116
  export function createExtractor(
80
117
  { logger = console, platform = 'web' }: ExtractorOptions = { logger: console }
81
118
  ) {
@@ -217,7 +254,7 @@ export function createExtractor(
217
254
  }
218
255
  }
219
256
 
220
- // we load gui delayed because we need to set some global/env stuff before importing
257
+ // we load hanzogui delayed because we need to set some global/env stuff before importing
221
258
  // otherwise we'd import `rnw` and cause it to evaluate react-native-web which causes errors
222
259
 
223
260
  function loadSync(props: GuiOptions) {
@@ -242,7 +279,7 @@ export function createExtractor(
242
279
  loadGui: load,
243
280
  loadGuiSync: loadSync,
244
281
  getGui() {
245
- return projectInfo?.guiConfig
282
+ return projectInfo?.hanzoguiConfig
246
283
  },
247
284
  parseSync: (f: FileOrPath, props: ExtractorParseProps) => {
248
285
  globalThis.expo ||= {} // expo-modules-core checks this and avoids loading "native" modules if exists
@@ -257,12 +294,12 @@ export function createExtractor(
257
294
  }
258
295
 
259
296
  function parseWithConfig(
260
- { components, guiConfig }: GuiProjectInfo,
297
+ { components, hanzoguiConfig }: GuiProjectInfo,
261
298
  fileOrPath: FileOrPath,
262
299
  options: ExtractorParseProps
263
300
  ) {
264
301
  const {
265
- config = 'gui.config.ts',
302
+ config = 'hanzogui.config.ts',
266
303
  importsWhitelist = ['constants.js'],
267
304
  evaluateVars = true,
268
305
  sourcePath = '',
@@ -288,7 +325,7 @@ export function createExtractor(
288
325
  styledCheckCache.delete(sourcePath)
289
326
  }
290
327
 
291
- if (sourcePath.includes('.gui-dynamic-eval')) {
328
+ if (sourcePath.includes('.hanzogui-dynamic-eval')) {
292
329
  return null
293
330
  }
294
331
 
@@ -355,10 +392,26 @@ export function createExtractor(
355
392
  pseudoDescriptors[name] ||
356
393
  // don't disable variants or else you lose many things flattening
357
394
  staticConfig.variants?.[name] ||
358
- projectInfo?.guiConfig?.shorthands[name]
395
+ projectInfo?.hanzoguiConfig?.shorthands[name]
359
396
  )
360
397
  }
361
398
 
399
+ function getGroupPseudo(name: string) {
400
+ const [_, groupName, a, b, c] = name.split('-')
401
+ if (!groupName) return
402
+ const m2 = a && b ? `${a}-${b}` : ''
403
+ const media = (m2 && mediaQueryConfig[m2] && m2) || (a && mediaQueryConfig[a] && a)
404
+ return media
405
+ ? media === m2
406
+ ? c
407
+ : b
408
+ ? `${b}${c ? `-${c}` : ''}`
409
+ : undefined
410
+ : a
411
+ ? `${a}${b ? `-${b}` : ''}${c ? `-${c}` : ''}`
412
+ : undefined
413
+ }
414
+
362
415
  /**
363
416
  * Step 1: Determine if importing any statically extractable components
364
417
  */
@@ -384,7 +437,7 @@ export function createExtractor(
384
437
  ].join(' ')
385
438
  )
386
439
  }
387
- if (process.env.DEBUG?.startsWith('gui')) {
440
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
388
441
  logger.info(
389
442
  [
390
443
  'loaded:',
@@ -394,12 +447,12 @@ export function createExtractor(
394
447
  }
395
448
  }
396
449
 
397
- tm.mark('load-gui', !!shouldPrintDebug)
450
+ tm.mark('load-hanzogui', !!shouldPrintDebug)
398
451
 
399
452
  if (!isFullyDisabled(options)) {
400
- if (!guiConfig?.themes) {
453
+ if (!hanzoguiConfig?.themes) {
401
454
  console.error(
402
- `⛔️ Error: Missing "themes" in your gui.config file:
455
+ `⛔️ Error: Missing "themes" in your hanzogui.config file:
403
456
 
404
457
  You may not need the compiler! Remember you can run Gui with no configuration at all.
405
458
 
@@ -410,17 +463,17 @@ export function createExtractor(
410
463
  - or search your lockfile for mis-matches.
411
464
  `
412
465
  )
413
- console.info(` Got config:`, guiConfig)
466
+ console.info(` Got config:`, hanzoguiConfig)
414
467
  process.exit(0)
415
468
  }
416
469
  }
417
470
 
418
- const firstThemeName = Object.keys(guiConfig?.themes || {})[0]
419
- const firstTheme = guiConfig?.themes[firstThemeName] || {}
471
+ const firstThemeName = Object.keys(hanzoguiConfig?.themes || {})[0]
472
+ const firstTheme = hanzoguiConfig?.themes[firstThemeName] || {}
420
473
 
421
474
  if (!firstTheme || typeof firstTheme !== 'object') {
422
475
  const err = `Missing theme ${firstThemeName}, an error occurred when importing your config`
423
- console.info(err, `Got config:`, guiConfig)
476
+ console.info(err, `Got config:`, hanzoguiConfig)
424
477
  console.info(`Looking for theme:`, firstThemeName)
425
478
  throw new Error(err)
426
479
  }
@@ -443,9 +496,9 @@ export function createExtractor(
443
496
  if (!isFullyDisabled(options)) {
444
497
  if (Object.keys(components || []).length === 0) {
445
498
  console.warn(
446
- `Warning: Gui didn't find any valid components (DEBUG=gui for more)`
499
+ `Warning: Gui didn't find any valid components (DEBUG=hanzogui for more)`
447
500
  )
448
- if (process.env.DEBUG === 'gui') {
501
+ if (process.env.DEBUG === 'hanzogui') {
449
502
  console.info(`components`, Object.keys(components || []), components)
450
503
  }
451
504
  }
@@ -487,7 +540,7 @@ export function createExtractor(
487
540
 
488
541
  if (extractStyledDefinitions && enableDynamicEvaluation) {
489
542
  // check all imports for `styled`, not just valid packages
490
- // styled( is basically guaranteed to be gui regardless of source
543
+ // styled( is basically guaranteed to be hanzogui regardless of source
491
544
  if (node.specifiers.some((specifier) => specifier.local.name === 'styled')) {
492
545
  doesUseValidImport = true
493
546
  // don't break - need to collect all import declarations for the styled() handler
@@ -691,7 +744,7 @@ export function createExtractor(
691
744
  } catch (err: any) {
692
745
  if (shouldPrintDebug) {
693
746
  logger.info(
694
- `skip optimize styled(${variableName}), unable to pre-process (DEBUG=gui for more)`
747
+ `skip optimize styled(${variableName}), unable to pre-process (DEBUG=hanzogui for more)`
695
748
  )
696
749
  }
697
750
  }
@@ -895,7 +948,7 @@ export function createExtractor(
895
948
  return
896
949
  }
897
950
 
898
- // validate its a proper import from gui (or internally inside gui)
951
+ // validate its a proper import from hanzogui (or internally inside hanzogui)
899
952
  const binding = traversePath.scope.getBinding(node.name.name)
900
953
  let moduleName = ''
901
954
  let dynamicComponent: { staticConfig: any } | null = null
@@ -1086,15 +1139,28 @@ export function createExtractor(
1086
1139
  ...(staticConfig.inlineProps || []),
1087
1140
  ])
1088
1141
 
1142
+ const canFlattenTransition =
1143
+ isTargetingHTML &&
1144
+ hanzoguiConfig?.animations.outputStyle === 'css' &&
1145
+ !hanzoguiConfig.animationDrivers
1146
+
1089
1147
  const deoptProps = new Set([
1090
- // always de-opt animation these
1148
+ // css-only transitions lower to ordinary css; every runtime driver
1149
+ // needs the component preserved so it can respond to prop changes.
1091
1150
  'animation',
1151
+ ...(canFlattenTransition ? [] : ['transition']),
1092
1152
  'animateOnly',
1093
1153
  'animatePresence',
1094
1154
  'disableOptimization',
1095
1155
 
1096
1156
  ...(!isTargetingHTML
1097
1157
  ? [
1158
+ // native has no css pseudo selectors; these are runtime-only on
1159
+ // rn (event listeners + style merge in createComponent), and if
1160
+ // we let them flatten into the stylesheet they get written
1161
+ // under a literal key that rn treats as an unknown style prop.
1162
+ // hover is intentionally excluded: it is no-op on native and
1163
+ // should be dropped rather than preserved as runtime work.
1098
1164
  'pressStyle',
1099
1165
  'focusStyle',
1100
1166
  'focusVisibleStyle',
@@ -1104,7 +1170,7 @@ export function createExtractor(
1104
1170
  : []),
1105
1171
 
1106
1172
  // when using a non-CSS driver, de-opt on enterStyle/exitStyle
1107
- ...(guiConfig?.animations.isReactNative
1173
+ ...(hanzoguiConfig?.animations.isReactNative
1108
1174
  ? ['enterStyle', 'exitStyle']
1109
1175
  : []),
1110
1176
  ])
@@ -1176,7 +1242,7 @@ export function createExtractor(
1176
1242
  style: {},
1177
1243
  theme: defaultTheme,
1178
1244
  viewProps: defaultProps,
1179
- conf: guiConfig!,
1245
+ conf: hanzoguiConfig!,
1180
1246
  props: defaultProps,
1181
1247
  componentState,
1182
1248
  styleProps: {
@@ -1288,9 +1354,9 @@ export function createExtractor(
1288
1354
 
1289
1355
  const name = attribute.name.name
1290
1356
 
1291
- // in gui style is handled at the end of the style loop so its not as simple as just
1357
+ // in hanzogui style is handled at the end of the style loop so its not as simple as just
1292
1358
  // adding this as a "style" property
1293
- // its not used often when using gui so not optimizing it for now
1359
+ // its not used often when using hanzogui so not optimizing it for now
1294
1360
  if (name === 'style') {
1295
1361
  shouldDeopt = true
1296
1362
  return null
@@ -1368,6 +1434,20 @@ export function createExtractor(
1368
1434
  return [attribute.value!, path.get('value')!] as const
1369
1435
  })()
1370
1436
 
1437
+ // these props have runtime-only meaning on native. decide from the
1438
+ // original jsx attr, before getSplitStyles has a chance to drop
1439
+ // native-dead work like hoverStyle from its static output.
1440
+ if (
1441
+ deoptProps.has(name) ||
1442
+ (platform === 'native' &&
1443
+ name[0] === '$' &&
1444
+ (name.startsWith('$theme-') ||
1445
+ (name.startsWith('$group-') && getGroupPseudo(name) !== 'hover')))
1446
+ ) {
1447
+ inlined.set(name, true)
1448
+ return attr
1449
+ }
1450
+
1371
1451
  const remove = () => {
1372
1452
  Array.isArray(valuePath)
1373
1453
  ? valuePath.map((p) => p.remove())
@@ -1420,9 +1500,33 @@ export function createExtractor(
1420
1500
  return attr
1421
1501
  }
1422
1502
 
1503
+ // static `group="<literal>"` is handled at compile-time in
1504
+ // extractToClassNames (emits container CSS + adds `t_group_<name>`
1505
+ // className), so we drop the JSX attribute here without bailing
1506
+ // flattening. dynamic `group={expr}` falls through to runtime.
1507
+ if (isTargetingHTML && name === 'group' && t.isStringLiteral(value)) {
1508
+ return []
1509
+ }
1510
+
1423
1511
  // if value can be evaluated, extract it and filter it out
1424
1512
  const styleValue = attemptEvalSafe(value)
1425
1513
 
1514
+ // media-like blocks with nested $-keys (eg $theme-dark={{ $sm: {…} }})
1515
+ // can't resolve to static CSS in one pass — keep them on the runtime path
1516
+ if (
1517
+ name[0] === '$' &&
1518
+ (name.startsWith('$theme-') || name.startsWith('$group-')) &&
1519
+ styleValue &&
1520
+ typeof styleValue === 'object' &&
1521
+ Object.keys(styleValue).some((k) => k[0] === '$')
1522
+ ) {
1523
+ if (shouldPrintDebug) {
1524
+ logger.info(` ! nested media-like key inside ${name}, deopt to runtime`)
1525
+ }
1526
+ inlined.set(name, true)
1527
+ return attr
1528
+ }
1529
+
1426
1530
  // never flatten if a prop isn't a valid static attribute
1427
1531
  // only post prop-mapping
1428
1532
  if (!variants[name] && !isValidStyleKey(name, staticConfig)) {
@@ -1444,6 +1548,12 @@ export function createExtractor(
1444
1548
  )
1445
1549
  // remove className - we dont use rnw styling
1446
1550
  delete out.className
1551
+ // remove style - rnw createDOMProps unconditionally emits a
1552
+ // (possibly empty) style key, but we passed it a single
1553
+ // non-style prop. Leaving it in causes Object.keys(out) to
1554
+ // iterate twice and emit the original JSXAttribute twice
1555
+ // (e.g. duplicate testID), breaking the DOM output.
1556
+ delete out.style
1447
1557
  }
1448
1558
  }
1449
1559
 
@@ -1467,6 +1577,23 @@ export function createExtractor(
1467
1577
  key === '__source' ||
1468
1578
  key === '__self'
1469
1579
  ) {
1580
+ if (
1581
+ styleValue === FAILED_EVAL &&
1582
+ key !== name &&
1583
+ t.isJSXAttribute(attr.value)
1584
+ ) {
1585
+ // createDOMProps renamed the prop (e.g. testID -> data-testid).
1586
+ // preserve the original expression value but use the new
1587
+ // attribute name. restricted to FAILED_EVAL because the
1588
+ // later `case 'attr'` rename pass only runs on
1589
+ // statically-evaluable values; for static values that pass
1590
+ // intentionally preserves some prop names (e.g. focusable
1591
+ // in v2) instead of doing the createDOMProps rename.
1592
+ return {
1593
+ type: 'attr',
1594
+ value: t.jsxAttribute(t.jsxIdentifier(key), attr.value.value),
1595
+ } as const
1596
+ }
1470
1597
  return attr
1471
1598
  }
1472
1599
  if (shouldPrintDebug) {
@@ -1502,15 +1629,25 @@ export function createExtractor(
1502
1629
  }
1503
1630
 
1504
1631
  if (isValidStyleKey(name, staticConfig)) {
1505
- // $theme-, $group- styles should not be flattened (needs runtime handling)
1506
- // $platform- can be flattened if the platform matches
1632
+ // $theme- / $group- styles extract through the atomic-CSS pipeline
1633
+ // (extractToClassNames createMediaStyle), so they fall through to
1634
+ // the normal style return below. The one case we still bail is
1635
+ // $group-<name>-* when an ancestor element declares `group="<name>"`
1636
+ // together with `untilMeasured` — the runtime measures the parent
1637
+ // and only then emits child styles, which can't be modeled in CSS.
1638
+ // $platform- can be flattened if the platform matches.
1507
1639
  if (name[0] === '$') {
1508
- if (name.startsWith('$theme-') || name.startsWith('$group-')) {
1509
- if (shouldPrintDebug) {
1510
- logger.info(` ! not flattening media-like style: ${name}`)
1640
+ if (name.startsWith('$group-')) {
1641
+ const groupName = name.slice('$group-'.length).split('-')[0]
1642
+ if (groupName && hasUntilMeasuredAncestor(path, groupName)) {
1643
+ if (shouldPrintDebug) {
1644
+ logger.info(
1645
+ ` ! group="${groupName}" ancestor has untilMeasured, not flattening: ${name}`
1646
+ )
1647
+ }
1648
+ inlined.set(name, true)
1649
+ return attr
1511
1650
  }
1512
- inlined.set(name, true)
1513
- return attr
1514
1651
  }
1515
1652
 
1516
1653
  // $platform-web, $platform-native, $platform-ios, $platform-android, $platform-tv, $platform-androidtv, $platform-tvos
@@ -1878,7 +2015,6 @@ export function createExtractor(
1878
2015
  })
1879
2016
 
1880
2017
  if (!shouldFlatten) {
1881
- // were no longer partially optimizing, it adds a lot of complexity for dubious performance
1882
2018
  if (shouldPrintDebug) {
1883
2019
  logger.info(
1884
2020
  `Deopting ${JSON.stringify({
@@ -1911,7 +2047,7 @@ export function createExtractor(
1911
2047
  if (!isValidStyleKey(key, staticConfig)) {
1912
2048
  return []
1913
2049
  }
1914
- const name = guiConfig?.shorthands[key] || key
2050
+ const name = hanzoguiConfig?.shorthands[key] || key
1915
2051
  if (value === undefined) {
1916
2052
  logger.warn(
1917
2053
  `⚠️ Error evaluating default style for component, prop ${key} ${value}`
@@ -2155,6 +2291,10 @@ export function createExtractor(
2155
2291
  )
2156
2292
  // remove rnw className use ours
2157
2293
  out.className = cn
2294
+ // see note in single-prop branch above; createDOMProps
2295
+ // also emits a stray style key here that would duplicate
2296
+ // emitted JSXAttributes downstream.
2297
+ delete out.style
2158
2298
  }
2159
2299
  if (shouldPrintDebug) {
2160
2300
  logger.info([' - expanded variant', name, out].join(' '))
@@ -2194,7 +2334,7 @@ export function createExtractor(
2194
2334
 
2195
2335
  let key = Object.keys(cur.value)[0]
2196
2336
  const value = cur.value[key]
2197
- const fullKey = guiConfig?.shorthands[key]
2337
+ const fullKey = hanzoguiConfig?.shorthands[key]
2198
2338
  // expand shorthands
2199
2339
  if (fullKey) {
2200
2340
  cur.value = { [fullKey]: value }
@@ -2275,8 +2415,37 @@ export function createExtractor(
2275
2415
  const before = process.env.IS_STATIC
2276
2416
  process.env.IS_STATIC = 'is_static'
2277
2417
  try {
2418
+ // $group-* / $theme-* keys carry block-form style objects that
2419
+ // getSplitStyles drops in static mode (no parent group context,
2420
+ // no theme value to read). Pluck them out so the atomic-CSS
2421
+ // pipeline in extractToClassNames can emit @container / theme
2422
+ // rules for them directly.
2423
+ let extractedMediaLikeProps: Record<string, any> | null = null
2424
+ let propsForSplit: any = props
2425
+ for (const k in props) {
2426
+ if (
2427
+ k[0] === '$' &&
2428
+ (k.startsWith('$group-') || k.startsWith('$theme-'))
2429
+ ) {
2430
+ if (propsForSplit === props) {
2431
+ propsForSplit = { ...props }
2432
+ }
2433
+ if (
2434
+ platform === 'native' &&
2435
+ k.startsWith('$group-') &&
2436
+ getGroupPseudo(k) === 'hover'
2437
+ ) {
2438
+ delete propsForSplit[k]
2439
+ continue
2440
+ }
2441
+ extractedMediaLikeProps ||= {}
2442
+ extractedMediaLikeProps[k] = propsForSplit[k]
2443
+ delete propsForSplit[k]
2444
+ }
2445
+ }
2446
+
2278
2447
  const out = getSplitStyles(
2279
- props,
2448
+ propsForSplit,
2280
2449
  staticConfig,
2281
2450
  defaultTheme,
2282
2451
  '',
@@ -2297,10 +2466,47 @@ export function createExtractor(
2297
2466
  debugPropValue || shouldPrintDebug
2298
2467
  )!
2299
2468
 
2469
+ // resolve tokens inside the plucked blocks: they skipped the main
2470
+ // split, so values like "$color5" would flow raw into the emitted
2471
+ // CSS where browsers reject the declaration. run each block through
2472
+ // its own static split so tokens become var(--x) references.
2473
+ // (native never extracts these — it deopts below — so web only.)
2474
+ if (extractedMediaLikeProps && platform !== 'native') {
2475
+ for (const k in extractedMediaLikeProps) {
2476
+ const block = extractedMediaLikeProps[k]
2477
+ if (!block || typeof block !== 'object') continue
2478
+ const blockOut = getSplitStyles(
2479
+ block,
2480
+ staticConfig,
2481
+ defaultTheme,
2482
+ '',
2483
+ componentState,
2484
+ {
2485
+ ...styleProps,
2486
+ noClass: true,
2487
+ fallbackProps: completeProps,
2488
+ },
2489
+ undefined,
2490
+ undefined,
2491
+ undefined,
2492
+ undefined,
2493
+ false,
2494
+ debugPropValue || shouldPrintDebug
2495
+ )
2496
+ if (blockOut) {
2497
+ extractedMediaLikeProps[k] = {
2498
+ ...blockOut.style,
2499
+ ...blockOut.pseudos,
2500
+ }
2501
+ }
2502
+ }
2503
+ }
2504
+
2300
2505
  let outProps = {
2301
2506
  ...(includeProps ? out.viewProps : {}),
2302
2507
  ...out.style,
2303
2508
  ...out.pseudos,
2509
+ ...extractedMediaLikeProps,
2304
2510
  }
2305
2511
 
2306
2512
  // check de-opt props again
@@ -2308,6 +2514,20 @@ export function createExtractor(
2308
2514
  if (deoptProps.has(key)) {
2309
2515
  shouldFlatten = false
2310
2516
  }
2517
+ // native has no atomic-CSS sink for theme- / group- pseudo
2518
+ // blocks; if they flatten they get serialized under the literal
2519
+ // `$theme-…` / `$group-…` key into the RN StyleSheet, where the
2520
+ // runtime's @container / theme-name matching never runs. de-opt
2521
+ // → preserve as inline prop so getSplitStyles handles them at
2522
+ // render time.
2523
+ if (
2524
+ platform === 'native' &&
2525
+ key[0] === '$' &&
2526
+ (key.startsWith('$theme-') ||
2527
+ (key.startsWith('$group-') && getGroupPseudo(key) !== 'hover'))
2528
+ ) {
2529
+ shouldFlatten = false
2530
+ }
2311
2531
  }
2312
2532
 
2313
2533
  if (shouldPrintDebug) {
@@ -2622,7 +2842,7 @@ export function createExtractor(
2622
2842
  node,
2623
2843
  lineNumbers,
2624
2844
  filePath,
2625
- config: guiConfig!,
2845
+ config: hanzoguiConfig!,
2626
2846
  flatNodeName,
2627
2847
  attemptEval,
2628
2848
  jsxPath: traversePath,
@@ -198,8 +198,8 @@ export const isValidImport = (
198
198
  }
199
199
 
200
200
  const getValidComponentPackages = memoize((props: GuiOptionsWithFileInfo) => {
201
- // just always look for `gui` and `@hanzogui/core`
202
- return [...new Set(['@hanzogui/core', 'gui', ...(props.components || [])])]
201
+ // just always look for `hanzogui` and `@hanzogui/core`
202
+ return [...new Set(['@hanzogui/core', 'hanzogui', ...(props.components || [])])]
203
203
  })
204
204
 
205
205
  export const getValidComponentsPaths = memoize((props: GuiOptionsWithFileInfo) => {
@@ -12,7 +12,7 @@ export function extractMediaStyle(
12
12
  props: GuiOptionsWithFileInfo,
13
13
  ternary: Ternary,
14
14
  jsxPath: NodePath<t.JSXElement>,
15
- guiConfig: GuiInternalConfig,
15
+ hanzoguiConfig: GuiInternalConfig,
16
16
  sourcePath: string,
17
17
  importance = 0,
18
18
  shouldPrintDebug: boolean | 'verbose' = false
@@ -23,9 +23,9 @@ export function extractMediaStyle(
23
23
  return null
24
24
  }
25
25
  const { key } = mt
26
- const mq = guiConfig.media[key]
26
+ const mq = hanzoguiConfig.media[key]
27
27
  if (!mq) {
28
- console.error(`Media query "${key}" not found: ${Object.keys(guiConfig.media)}`)
28
+ console.error(`Media query "${key}" not found: ${Object.keys(hanzoguiConfig.media)}`)
29
29
  return null
30
30
  }
31
31
  const getStyleObj = (styleObj: ViewStyle | null, negate = false) => {
@@ -40,7 +40,7 @@ export function extractMediaStyle(
40
40
  return null
41
41
  }
42
42
  // for now order first strongest
43
- const mediaKeys = Object.keys(guiConfig.media)
43
+ const mediaKeys = Object.keys(hanzoguiConfig.media)
44
44
  const mediaKeyPrecendence = mediaKeys.reduce((acc, cur, i) => {
45
45
  acc[cur] = new Array(importance + 1).fill(':root').join('')
46
46
  return acc
@@ -57,7 +57,7 @@ export function extractMediaStyle(
57
57
  const mediaStyle = core.createMediaStyle(
58
58
  style,
59
59
  key,
60
- guiConfig.media,
60
+ hanzoguiConfig.media,
61
61
  true,
62
62
  negate
63
63
  )