@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
package/src/checkDeps.ts CHANGED
@@ -22,10 +22,10 @@ export type Options = {
22
22
  }
23
23
 
24
24
  // critical packages that must not be duplicated at runtime
25
- const CRITICAL_PACKAGES = ['@hanzogui/web', '@hanzogui/core', 'gui']
25
+ const CRITICAL_PACKAGES = ['@hanzogui/web', '@hanzogui/core', 'hanzogui']
26
26
 
27
27
  /**
28
- * Walks node_modules to find duplicate physical copies of critical gui packages.
28
+ * Walks node_modules to find duplicate physical copies of critical hanzogui packages.
29
29
  * Detects nested node_modules that would cause multiple runtime instances.
30
30
  */
31
31
  function checkDuplicateInstalls(root: string): string {
@@ -60,7 +60,7 @@ function checkDuplicateInstalls(root: string): string {
60
60
  if (duplicates.size === 0) return ''
61
61
 
62
62
  const lines: string[] = [
63
- 'Found duplicate gui installations in node_modules:',
63
+ 'Found duplicate hanzogui installations in node_modules:',
64
64
  '',
65
65
  'This causes multiple runtime instances, which breaks theme/config detection.',
66
66
  '',
@@ -92,7 +92,7 @@ function checkDuplicateInstalls(root: string): string {
92
92
 
93
93
  /**
94
94
  * Recursively find all instances of a package in node_modules.
95
- * Handles both scoped (@hanzogui/web) and unscoped (gui) packages.
95
+ * Handles both scoped (@hanzogui/web) and unscoped (hanzogui) packages.
96
96
  */
97
97
  function findAllInstances(
98
98
  nodeModulesDir: string,
@@ -139,7 +139,7 @@ function findAllInstances(
139
139
  }
140
140
 
141
141
  /**
142
- * Checks lockfile for multiple resolved versions of gui packages.
142
+ * Checks lockfile for multiple resolved versions of hanzogui packages.
143
143
  * Supports bun.lock, yarn.lock, and package-lock.json.
144
144
  */
145
145
  function checkLockfileDuplicates(root: string): string {
@@ -162,7 +162,7 @@ function checkBunLockDuplicates(lockPath: string): string {
162
162
 
163
163
  // match patterns like "@hanzogui/web@version" or "hanzogui@version" in resolved entries
164
164
  // bun.lock format: "package@version": ["resolved-url", ...]
165
- const packagePattern = /["'](@hanzogui\/[\w-]+|gui)@([^"'\s,]+)["']/g
165
+ const packagePattern = /["'](@hanzogui\/[\w-]+|hanzogui)@([^"'\s,]+)["']/g
166
166
  let match: RegExpExecArray | null
167
167
  while ((match = packagePattern.exec(content)) !== null) {
168
168
  const name = match[1]
@@ -189,7 +189,7 @@ function checkYarnLockDuplicates(lockPath: string): string {
189
189
  // yarn.lock format:
190
190
  // "@hanzogui/web@^1.0.0":
191
191
  // version "1.0.1"
192
- const entryPattern = /^"?(@hanzogui\/[\w-]+|gui)@[^":\n]+[":]?\s*$/gm
192
+ const entryPattern = /^"?(@hanzogui\/[\w-]+|hanzogui)@[^":\n]+[":]?\s*$/gm
193
193
  const versionPattern = /^\s+version\s+"([^"]+)"/gm
194
194
 
195
195
  let entryMatch: RegExpExecArray | null
@@ -260,21 +260,21 @@ function formatLockfileDuplicates(
260
260
  lines.push(
261
261
  'Multiple versions cause duplicate runtime instances, breaking config/theme detection.'
262
262
  )
263
- lines.push('Fix: ensure all gui packages use the same version range, then dedupe.')
263
+ lines.push('Fix: ensure all hanzogui packages use the same version range, then dedupe.')
264
264
 
265
265
  return lines.join('\n')
266
266
  }
267
267
 
268
268
  /**
269
- * Checks that a gui config file exists in common locations.
269
+ * Checks that a hanzogui config file exists in common locations.
270
270
  */
271
271
  function checkConfigExists(root: string): string {
272
272
  const configNames = [
273
- 'gui.config.ts',
274
- 'gui.config.tsx',
275
- 'gui.config.js',
276
- 'gui.config.mjs',
277
- 'gui.config.cjs',
273
+ 'hanzogui.config.ts',
274
+ 'hanzogui.config.tsx',
275
+ 'hanzogui.config.js',
276
+ 'hanzogui.config.mjs',
277
+ 'hanzogui.config.cjs',
278
278
  ]
279
279
 
280
280
  const searchDirs = [root, join(root, 'src'), join(root, 'app'), join(root, 'config')]
@@ -287,12 +287,12 @@ function checkConfigExists(root: string): string {
287
287
  }
288
288
  }
289
289
 
290
- // check if gui.build.ts references a config path
290
+ // check if hanzogui.build.ts references a config path
291
291
  const buildConfigNames = [
292
- 'gui.build.ts',
293
- 'gui.build.js',
294
- 'gui.build.mjs',
295
- 'gui.build.cjs',
292
+ 'hanzogui.build.ts',
293
+ 'hanzogui.build.js',
294
+ 'hanzogui.build.mjs',
295
+ 'hanzogui.build.cjs',
296
296
  ]
297
297
  for (const name of buildConfigNames) {
298
298
  const buildPath = join(root, name)
@@ -308,13 +308,13 @@ function checkConfigExists(root: string): string {
308
308
  }
309
309
  }
310
310
 
311
- // also check if there's a gui config referenced in package.json
311
+ // also check if there's a hanzogui config referenced in package.json
312
312
  const pkgJsonPath = join(root, 'package.json')
313
313
  if (existsSync(pkgJsonPath)) {
314
314
  try {
315
315
  const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
316
- if (pkg.gui?.config) {
317
- const configPath = join(root, pkg.gui.config)
316
+ if (pkg.hanzogui?.config) {
317
+ const configPath = join(root, pkg.hanzogui.config)
318
318
  if (existsSync(configPath)) return ''
319
319
  }
320
320
  } catch {}
@@ -329,12 +329,12 @@ function checkConfigExists(root: string): string {
329
329
  }
330
330
 
331
331
  return [
332
- 'No gui.config file found.',
332
+ 'No hanzogui.config file found.',
333
333
  '',
334
- 'Gui requires a config file (e.g. gui.config.ts) that calls createGui().',
334
+ 'Gui requires a config file (e.g. hanzogui.config.ts) that calls createGui().',
335
335
  'Without it, components will throw "Can\'t find Gui configuration" at runtime.',
336
336
  '',
337
- 'See: https://gui.dev/docs/core/configuration',
337
+ 'See: https://hanzogui.dev/docs/core/configuration',
338
338
  ].join('\n')
339
339
  }
340
340
 
package/src/constants.ts CHANGED
@@ -6,9 +6,9 @@ export const CSS_FILE_NAME = '__snack.css'
6
6
  export const MEDIA_SEP = '_'
7
7
 
8
8
  // ensure cache dir
9
- export const cacheDir = findCacheDir({ name: 'gui', create: true })
9
+ export const cacheDir = findCacheDir({ name: 'hanzogui', create: true })
10
10
 
11
11
  export const FAILED_EVAL = Symbol('failed_style_eval')
12
12
 
13
13
  export const SHOULD_DEBUG =
14
- process.env.DEBUG === '*' || process.env.DEBUG?.startsWith('gui')
14
+ process.env.DEBUG === '*' || process.env.DEBUG?.startsWith('hanzogui')
package/src/exports.ts CHANGED
@@ -12,4 +12,5 @@ export * from './extractor/watchGuiConfig'
12
12
  export * from './extractor/createLogger'
13
13
  export * from './registerRequire'
14
14
  export { detectModuleFormat, clearFormatCache } from './extractor/detectModuleFormat'
15
+ export { esbundleGuiConfig } from './extractor/bundle'
15
16
  export * from './getPragmaOptions'
@@ -53,25 +53,54 @@ type Props = Omit<Partial<esbuild.BuildOptions>, 'entryPoints'> & {
53
53
  }
54
54
 
55
55
  function getESBuildConfig(
56
- { entryPoints, resolvePlatformSpecificEntries, ...options }: Props,
56
+ {
57
+ entryPoints,
58
+ resolvePlatformSpecificEntries,
59
+ define: callerDefine,
60
+ ...options
61
+ }: Props,
57
62
  platform: GuiPlatform,
58
63
  aliases?: Record<string, string>
59
64
  ) {
60
- if (process.env.DEBUG?.startsWith('gui')) {
65
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
61
66
  console.info(`Building`, entryPoints)
62
67
  }
63
68
 
64
69
  const resolvedEntryPoints = !resolvePlatformSpecificEntries
65
70
  ? entryPoints
66
- : entryPoints.map(resolveWebOrNativeSpecificEntry)
71
+ : entryPoints.map((entry) => resolveWebOrNativeSpecificEntry(entry, platform))
67
72
 
68
73
  // detect format from entry points if not explicitly provided by caller
69
74
  const detectedFormat = options.format || detectEntryFormat(resolvedEntryPoints[0])
70
75
 
76
+ // inline platform env vars for the bundled config + components.
77
+ // the bundled output runs in node afterward (CSS extraction time), at which
78
+ // point process.env reflects whatever the build tool's parent process had —
79
+ // not necessarily the platform we're bundling for. inlining via esbuild's
80
+ // define makes the bundle self-consistent regardless of host env, which
81
+ // matters most for vite/vxrn (which doesn't set GUI_TARGET globally
82
+ // because the same plugin handles native too) and for any code in the bundle
83
+ // graph that reads EXPO_OS (expo-modules-core's Platform.OS, etc.).
84
+ const platformDefines: Record<string, string> =
85
+ platform === 'web'
86
+ ? {
87
+ 'process.env.GUI_TARGET': '"web"',
88
+ 'process.env.EXPO_OS': '"web"',
89
+ }
90
+ : {
91
+ 'process.env.GUI_TARGET': '"native"',
92
+ // EXPO_OS doesn't have a useful "native" value (it's ios/android),
93
+ // so leave it alone here and let the consumer set it if needed.
94
+ }
95
+
71
96
  const res: esbuild.BuildOptions = {
72
97
  bundle: true,
73
98
  entryPoints: resolvedEntryPoints,
74
99
  format: detectedFormat,
100
+ define: {
101
+ ...platformDefines,
102
+ ...callerDefine,
103
+ },
75
104
  // for ESM: prefer "module" field for resolution, add require() shim for bundled CJS deps
76
105
  ...(detectedFormat === 'esm'
77
106
  ? {
@@ -87,7 +116,7 @@ function getESBuildConfig(
87
116
  allowOverwrite: true,
88
117
  keepNames: true,
89
118
  resolveExtensions: [
90
- ...(process.env.GUI_TARGET === 'web'
119
+ ...(platform === 'web'
91
120
  ? ['.web.tsx', '.web.ts', '.web.jsx', '.web.js']
92
121
  : ['.native.tsx', '.native.ts', '.native.jsx', '.native.js']),
93
122
  '.tsx',
@@ -148,8 +177,8 @@ function getESBuildConfig(
148
177
 
149
178
  // stub files with top-level await - they're typically runtime-only
150
179
  if (hasTopLevelAwait(contents, args.path)) {
151
- if (process.env.DEBUG?.startsWith('gui')) {
152
- console.info(`[gui] stubbing file with top-level await: ${args.path}`)
180
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
181
+ console.info(`[hanzogui] stubbing file with top-level await: ${args.path}`)
153
182
  }
154
183
  return {
155
184
  // Keep this as an ESM-shaped stub so esbuild doesn't inline a
@@ -33,7 +33,7 @@ function getDynamicEvalOutfile(name: string, format: 'esm' | 'cjs', contents: st
33
33
  .update(contents)
34
34
  .digest('hex')
35
35
  .slice(0, 10)
36
- return join(process.cwd(), '.gui', `dynamic-eval-${hash}-${basename(name)}.${ext}`)
36
+ return join(process.cwd(), '.hanzogui', `dynamic-eval-${hash}-${basename(name)}.${ext}`)
37
37
  }
38
38
 
39
39
  function getEsbuildStdinLoader(filePath: string): esbuild.Loader {
@@ -101,7 +101,7 @@ export type LoadedComponents = {
101
101
 
102
102
  export type GuiProjectInfo = {
103
103
  components?: LoadedComponents[]
104
- guiConfig?: GuiInternalConfig | null
104
+ hanzoguiConfig?: GuiInternalConfig | null
105
105
  nameToPaths?: NameToPaths
106
106
  cached?: boolean
107
107
  }
@@ -161,8 +161,8 @@ const handleEsmFeaturesPlugin: esbuild.Plugin = {
161
161
 
162
162
  // stub files with top-level await - they're typically runtime-only
163
163
  if (hasTopLevelAwait(contents, args.path)) {
164
- if (process.env.DEBUG?.startsWith('gui')) {
165
- console.info(`[gui] stubbing file with top-level await: ${args.path}`)
164
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
165
+ console.info(`[hanzogui] stubbing file with top-level await: ${args.path}`)
166
166
  }
167
167
  return {
168
168
  // Keep this as an ESM-shaped stub so esbuild doesn't inline a top-level
@@ -214,6 +214,7 @@ export type BundledConfig = Exclude<Awaited<ReturnType<typeof bundleConfig>>, un
214
214
 
215
215
  // will use cached one if watching
216
216
  let currentBundle: BundledConfig | null = null
217
+ let currentBundleKey = ''
217
218
  let isBundling = false
218
219
  let lastBundle: BundledConfig | null = null
219
220
  const waitForBundle = new Set<Function>()
@@ -230,22 +231,35 @@ let loadedConfig: GuiInternalConfig | null = null
230
231
 
231
232
  export const getLoadedConfig = () => loadedConfig
232
233
 
234
+ function getBundleKey(props: GuiOptions) {
235
+ return JSON.stringify({
236
+ components: props.components,
237
+ config: props.config,
238
+ platform: props.platform,
239
+ })
240
+ }
241
+
233
242
  export async function getBundledConfig(props: GuiOptions, rebuild = false) {
243
+ const bundleKey = getBundleKey(props)
234
244
  if (isBundling) {
235
245
  await new Promise((res) => {
236
246
  waitForBundle.add(res)
237
247
  })
238
- } else if (!currentBundle || rebuild) {
248
+ }
249
+
250
+ if (!currentBundle || currentBundleKey !== bundleKey || rebuild) {
239
251
  return await bundleConfig(props)
240
252
  }
253
+
241
254
  return currentBundle
242
255
  }
243
256
 
244
- global.guiLastLoaded ||= 0
257
+ global.hanzoguiLastLoaded ||= 0
245
258
 
246
- function updateLastLoaded(config: any) {
247
- global.guiLastLoaded = Date.now()
248
- global.guiLastBundledConfig = config
259
+ function updateLastLoaded(config: any, bundleKey: string) {
260
+ global.hanzoguiLastLoaded = Date.now()
261
+ global.hanzoguiLastBundledConfig = config
262
+ global.hanzoguiLastBundledConfigKey = bundleKey
249
263
  }
250
264
 
251
265
  let hasBundledOnce = false
@@ -256,10 +270,15 @@ let hasBundledOnce = false
256
270
  let hasLoggedBuild = false
257
271
 
258
272
  export async function bundleConfig(props: GuiOptions) {
273
+ const bundleKey = getBundleKey(props)
259
274
  // webpack is calling this a ton for no reason
260
- if (global.guiLastBundledConfig && Date.now() - global.guiLastLoaded < 3000) {
275
+ if (
276
+ global.hanzoguiLastBundledConfig &&
277
+ global.hanzoguiLastBundledConfigKey === bundleKey &&
278
+ Date.now() - global.hanzoguiLastLoaded < 3000
279
+ ) {
261
280
  // just loaded recently
262
- return global.guiLastBundledConfig
281
+ return global.hanzoguiLastBundledConfig
263
282
  }
264
283
 
265
284
  try {
@@ -268,11 +287,11 @@ export async function bundleConfig(props: GuiOptions) {
268
287
  const configEntry = props.config
269
288
  ? getGuiConfigPathFromOptionsConfig(props.config)
270
289
  : ''
271
- const tmpDir = join(process.cwd(), '.gui')
290
+ const tmpDir = join(process.cwd(), '.hanzogui')
272
291
  // detect module format from config entry point
273
292
  const configFormat = configEntry ? detectModuleFormat(configEntry) : 'cjs'
274
293
  const configExt = configFormat === 'esm' ? '.mjs' : '.cjs'
275
- const configOutPath = join(tmpDir, `gui.config${configExt}`)
294
+ const configOutPath = join(tmpDir, `hanzogui.config${configExt}`)
276
295
  const baseComponents = (props.components || []).filter((x) => x !== '@hanzogui/core')
277
296
  // detect format per component module
278
297
  const componentFormats: Array<'esm' | 'cjs'> = baseComponents.map((mod) => {
@@ -297,7 +316,7 @@ export async function bundleConfig(props: GuiOptions) {
297
316
 
298
317
  if (
299
318
  process.env.NODE_ENV === 'development' &&
300
- process.env.DEBUG?.startsWith('gui')
319
+ process.env.DEBUG?.startsWith('hanzogui')
301
320
  ) {
302
321
  console.info(`Building config entry`, configEntry)
303
322
  }
@@ -371,10 +390,10 @@ export async function bundleConfig(props: GuiOptions) {
371
390
  colorLog(
372
391
  Color.FgYellow,
373
392
  `
374
- ➡ [gui] built config, components, prompt (${Date.now() - start}ms)`
393
+ ➡ [hanzogui] built config, components, prompt (${Date.now() - start}ms)`
375
394
  )
376
395
 
377
- if (process.env.DEBUG?.startsWith('gui')) {
396
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
378
397
  colorLog(
379
398
  Color.Dim,
380
399
  `
@@ -427,7 +446,7 @@ export async function bundleConfig(props: GuiOptions) {
427
446
  // check for ProxyWorm - indicates a module loading error
428
447
  if (config._isProxyWorm) {
429
448
  throw new Error(
430
- `Got a proxied config - likely a module loading error. Set DEBUG=gui for details.`
449
+ `Got a proxied config - likely a module loading error. Set DEBUG=hanzogui for details.`
431
450
  )
432
451
  }
433
452
 
@@ -459,7 +478,7 @@ export async function bundleConfig(props: GuiOptions) {
459
478
  component.moduleName
460
479
 
461
480
  if (!component.moduleName) {
462
- if (process.env.DEBUG?.includes('gui') || process.env.IS_GUI_DEV) {
481
+ if (process.env.DEBUG?.includes('hanzogui') || process.env.IS_GUI_DEV) {
463
482
  console.warn(
464
483
  `⚠️ no module name found: ${component.moduleName} ${JSON.stringify(
465
484
  baseComponents
@@ -471,7 +490,7 @@ export async function bundleConfig(props: GuiOptions) {
471
490
 
472
491
  if (
473
492
  process.env.NODE_ENV === 'development' &&
474
- process.env.DEBUG?.startsWith('gui')
493
+ process.env.DEBUG?.startsWith('hanzogui')
475
494
  ) {
476
495
  console.info('Loaded components', components)
477
496
  }
@@ -479,18 +498,19 @@ export async function bundleConfig(props: GuiOptions) {
479
498
  const res = {
480
499
  components,
481
500
  nameToPaths: {},
482
- guiConfig: config,
501
+ hanzoguiConfig: config,
483
502
  }
484
503
 
485
504
  currentBundle = res
486
- updateLastLoaded(res)
505
+ currentBundleKey = bundleKey
506
+ updateLastLoaded(res, bundleKey)
487
507
 
488
508
  return res
489
509
  } catch (err: any) {
490
510
  console.error(
491
- `Error bundling gui config: ${err?.message} (run with DEBUG=gui to see stack)`
511
+ `Error bundling hanzogui config: ${err?.message} (run with DEBUG=hanzogui to see stack)`
492
512
  )
493
- if (process.env.DEBUG?.includes('gui')) {
513
+ if (process.env.DEBUG?.includes('hanzogui')) {
494
514
  console.error(err.stack)
495
515
  }
496
516
  } finally {
@@ -502,7 +522,7 @@ export async function bundleConfig(props: GuiOptions) {
502
522
 
503
523
  export async function writeGuiCSS(outputCSS: string, config: GuiInternalConfig) {
504
524
  const flush = async () => {
505
- colorLog(Color.FgYellow, ` ➡ [gui] output css: ${outputCSS}`)
525
+ colorLog(Color.FgYellow, ` ➡ [hanzogui] output css: ${outputCSS}`)
506
526
  await FS.writeFile(outputCSS, css)
507
527
  }
508
528
 
@@ -624,7 +644,7 @@ export async function loadComponentsInner(
624
644
  })
625
645
  }
626
646
 
627
- if (process.env.DEBUG === 'gui') {
647
+ if (process.env.DEBUG === 'hanzogui') {
628
648
  console.info(`loadModule`, loadModule, format)
629
649
  }
630
650
 
@@ -666,7 +686,7 @@ export async function loadComponentsInner(
666
686
  } catch (err) {
667
687
  console.info('babel err', err, writtenContents)
668
688
  writtenContents = fileContents
669
- if (process.env.DEBUG?.startsWith('gui')) {
689
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
670
690
  console.info(`Error parsing babel likely`, err)
671
691
  }
672
692
 
@@ -779,7 +799,7 @@ export function loadComponentsInnerSync(
779
799
  })
780
800
  }
781
801
 
782
- if (process.env.DEBUG === 'gui') {
802
+ if (process.env.DEBUG === 'hanzogui') {
783
803
  console.info(`loadModule`, loadModule, require.resolve(loadModule))
784
804
  }
785
805
 
@@ -814,7 +834,7 @@ export function loadComponentsInnerSync(
814
834
  } catch (err) {
815
835
  console.info('babel err', err, writtenContents)
816
836
  writtenContents = fileContents
817
- if (process.env.DEBUG?.startsWith('gui')) {
837
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
818
838
  console.info(`Error parsing babel likely`, err)
819
839
  }
820
840
  } finally {
@@ -45,24 +45,9 @@ export function concatClassName(_cn: Record<string, any> | null | undefined): st
45
45
  continue
46
46
  }
47
47
 
48
- const nextChar = name[splitIndex + 1]
49
- // synced to static-ui constants
50
- // MEDIA_SEP
51
- const isMediaQuery = nextChar === '_'
52
- // PSEUDO_SEP
53
- // commenting out three things to make pseudos override properly
54
- // (leave in for a bit to see if other bugs pop up later):
55
- // 1. const isPseudoQuery = nextChar === '0'
56
48
  const styleKey = name.slice(1, name.indexOf('-'))
57
- // 2. isMediaQuery || isPseudoQuery
58
- // extract just the media query name (e.g., 'lg' '_pr-_lg_260px')
59
- // by finding the underscore after the media key name
60
- const mediaStart = splitIndex + 2
61
- const mediaEnd = name.indexOf('_', mediaStart)
62
- const mediaKey =
63
- isMediaQuery && mediaEnd > mediaStart ? name.slice(mediaStart, mediaEnd) : null
64
- const uid = mediaKey ? styleKey + mediaKey : styleKey
65
- // 3. && !isPseudoQuery
49
+ const { mediaKey, pseudoKey } = getClassNameScope(name, splitIndex)
50
+ const uid = `${styleKey}${mediaKey ? `@${mediaKey}` : ''}${pseudoKey ? `:${pseudoKey}` : ''}`
66
51
 
67
52
  if (usedPrefixes.has(uid)) {
68
53
  // if (shouldDebug) console.log('debug exclude:', usedPrefixes, name)
@@ -75,8 +60,8 @@ export function concatClassName(_cn: Record<string, any> | null | undefined): st
75
60
  if (propName && propObjects) {
76
61
  if (
77
62
  propObjects.some((po) => {
78
- if (mediaKey) {
79
- const propKey = pseudoInvert[mediaKey]
63
+ if (pseudoKey) {
64
+ const propKey = pseudoInvert[pseudoKey]
80
65
  return po && po[propKey] && propName in po[propKey] && po[propKey] !== null
81
66
  }
82
67
  const res = po && propName in po && po[propName] !== null
@@ -95,11 +80,43 @@ export function concatClassName(_cn: Record<string, any> | null | undefined): st
95
80
  return final.trim()
96
81
  }
97
82
 
83
+ function getClassNameScope(name: string, splitIndex: number) {
84
+ let mediaKey = ''
85
+ let pseudoKey = ''
86
+ let valueStart = splitIndex + 1
87
+
88
+ if (name[valueStart] === '_') {
89
+ const mediaEnd = name.indexOf('_', valueStart + 1)
90
+ if (mediaEnd > valueStart + 1) {
91
+ mediaKey = name.slice(valueStart + 1, mediaEnd)
92
+ valueStart = mediaEnd + 1
93
+ }
94
+ }
95
+
96
+ if (name[valueStart] === '0') {
97
+ const pseudoStart = valueStart + 1
98
+ for (const nextPseudoKey of pseudoKeys) {
99
+ if (name.startsWith(`${nextPseudoKey}-`, pseudoStart)) {
100
+ pseudoKey = nextPseudoKey
101
+ break
102
+ }
103
+ }
104
+ }
105
+
106
+ return { mediaKey, pseudoKey }
107
+ }
108
+
98
109
  const pseudoInvert = {
99
110
  hover: 'hoverStyle',
111
+ active: 'pressStyle',
100
112
  focus: 'focusStyle',
101
- press: 'pressStyle',
113
+ 'focus-visible': 'focusVisibleStyle',
114
+ 'focus-within': 'focusWithinStyle',
102
115
  focusVisible: 'focusVisibleStyle',
103
116
  focusWithin: 'focusWithinStyle',
104
117
  disabled: 'disabledStyle',
118
+ enter: 'enterStyle',
119
+ exit: 'exitStyle',
105
120
  }
121
+
122
+ const pseudoKeys = Object.keys(pseudoInvert).sort((a, b) => b.length - a.length)