inventive-ui 0.0.10 → 0.0.11

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import path27 from "path";
4
+ import path26 from "path";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // src/utils/ui.ts
@@ -190,7 +190,7 @@ var BANNER_COMPACT = [
190
190
  var FULL_BANNER_WIDTH = 101;
191
191
  function resolveCliVersion() {
192
192
  try {
193
- return true ? "0.0.10" : "1.0.0";
193
+ return true ? "0.0.11" : "1.0.0";
194
194
  } catch {
195
195
  return "1.0.0";
196
196
  }
@@ -373,8 +373,8 @@ function resolveApiBaseUrl() {
373
373
  );
374
374
  }
375
375
  if (parsed.pathname && parsed.pathname !== "/" && parsed.pathname !== "") {
376
- const path28 = parsed.pathname.replace(/\/+$/, "");
377
- if (path28 && !/^\/[a-zA-Z0-9._/-]+$/.test(path28)) {
376
+ const path27 = parsed.pathname.replace(/\/+$/, "");
377
+ if (path27 && !/^\/[a-zA-Z0-9._/-]+$/.test(path27)) {
378
378
  throw new CLIError(
379
379
  "IUI_API_URL path contains invalid characters.",
380
380
  "Use a simple path prefix such as /v1"
@@ -434,7 +434,7 @@ var COMPONENTS_PACKAGE = "@inventive-ui/components";
434
434
  var NPM_SCOPE = "@inventive-ui";
435
435
  var IUI_DIR = ".iui";
436
436
  var GLOBAL_CONFIG_DIR = ".iui";
437
- var PROJECT_CONFIG_FILE = "iui.config.ts";
437
+ var PROJECT_CONFIG_FILE = "theme.config.ts";
438
438
  var REQUIRED_REACT_MAJOR = 19;
439
439
  var REACT_SAFE_VERSION = "^19.0.0";
440
440
  var REQUIRED_VITE_MAJOR = 6;
@@ -596,7 +596,7 @@ var EMOJI_FAMILIES = [
596
596
  "twitter",
597
597
  "native"
598
598
  ];
599
- var DEFAULT_EMOJI_SKIN_TONE = "medium-light";
599
+ var DEFAULT_EMOJI_SKIN_TONE = "mediumLight";
600
600
  var EMOJI_FAMILY_LABELS = {
601
601
  apple: "Apple",
602
602
  google: "Google",
@@ -1428,7 +1428,7 @@ function resolveFrameworkScriptsDir(startCwd) {
1428
1428
  if (existsSync(loader)) return scriptsDir;
1429
1429
  }
1430
1430
  throw new CLIError(
1431
- `Cannot scaffold iui.config.ts: ${FRAMEWORK_PACKAGE} is not installed or is missing scripts/load-framework-theme-defaults.mjs.`
1431
+ `Cannot scaffold theme.config.ts: ${FRAMEWORK_PACKAGE} is not installed or is missing scripts/load-framework-theme-defaults.mjs.`
1432
1432
  );
1433
1433
  }
1434
1434
  function buildProjectConfigSource(cwd = process.cwd()) {
@@ -2043,7 +2043,6 @@ function mergeComponentConfigContent(source, manifest) {
2043
2043
  // src/utils/config-patch/tsconfig-iui.ts
2044
2044
  import path7 from "path";
2045
2045
  import fs6 from "fs-extra";
2046
- var IUI_TS_ROOT_FILES = ["iui.config.ts", "component.config.ts"];
2047
2046
  function isSolutionStyleTsconfig(config) {
2048
2047
  const refs = config.references;
2049
2048
  return Array.isArray(refs) && refs.length > 0;
@@ -2101,7 +2100,8 @@ function patchSolutionStyleTsconfigForIui(cwd) {
2101
2100
  if (!isSolutionStyleTsconfig(existing)) return false;
2102
2101
  const repairedRoot = repairSolutionStyleRootTsconfig(cwd);
2103
2102
  const appPath = resolveAppTsconfigPath(cwd, existing);
2104
- const patchedApp = appPath ? patchJsonInclude(appPath, IUI_TS_ROOT_FILES) : false;
2103
+ const themeFile = fs6.existsSync(path7.join(cwd, "iui.config.ts")) && !fs6.existsSync(path7.join(cwd, "theme.config.ts")) ? "iui.config.ts" : "theme.config.ts";
2104
+ const patchedApp = appPath ? patchJsonInclude(appPath, [themeFile, "component.config.ts"]) : false;
2105
2105
  return repairedRoot || patchedApp;
2106
2106
  }
2107
2107
 
@@ -2119,10 +2119,9 @@ var iuiThemeConfigSchema = z2.object({
2119
2119
  }).strict();
2120
2120
  var IuiThemeConfigSchema = iuiThemeConfigSchema.refine(
2121
2121
  (data) => !("assets" in data),
2122
- { message: "iui.config must not contain an assets key \u2014 use assets.config.json" }
2122
+ { message: "theme.config must not contain an assets key \u2014 use assets.config.json" }
2123
2123
  );
2124
2124
  var AssetsConfigSchema = z2.object({
2125
- binding: z2.enum(["lazy", "scanned"]).optional(),
2126
2125
  preload: z2.enum(["none", "configured", "scanned"]).optional(),
2127
2126
  icon: z2.object({
2128
2127
  library: z2.string().optional(),
@@ -2195,11 +2194,14 @@ function stripAssetsFromIuiConfig(content) {
2195
2194
  return next;
2196
2195
  }
2197
2196
  function checkIuiConfigTierBleed(cwd = process.cwd(), options = {}) {
2198
- const configPath = path8.join(cwd, PROJECT_CONFIG_FILE);
2197
+ const configPath = path8.join(
2198
+ cwd,
2199
+ fs7.existsSync(path8.join(cwd, PROJECT_CONFIG_FILE)) || !fs7.existsSync(path8.join(cwd, "iui.config.ts")) ? PROJECT_CONFIG_FILE : "iui.config.ts"
2200
+ );
2199
2201
  if (!fs7.existsSync(configPath)) {
2200
2202
  return {
2201
2203
  ok: false,
2202
- summary: "iui.config.ts not found",
2204
+ summary: "theme.config.ts not found",
2203
2205
  details: "Run iui init to scaffold project config."
2204
2206
  };
2205
2207
  }
@@ -2214,7 +2216,7 @@ function checkIuiConfigTierBleed(cwd = process.cwd(), options = {}) {
2214
2216
  }
2215
2217
  }
2216
2218
  if (issues.length === 0) {
2217
- return { ok: true, summary: "iui.config.ts tier boundaries are valid" };
2219
+ return { ok: true, summary: "theme.config.ts tier boundaries are valid" };
2218
2220
  }
2219
2221
  if (options.autoFix) {
2220
2222
  const fixed = stripAssetsFromIuiConfig(content);
@@ -2227,14 +2229,14 @@ function checkIuiConfigTierBleed(cwd = process.cwd(), options = {}) {
2227
2229
  if (remaining.length === 0 && /\bbuild\s*:\s*\{/.test(content)) {
2228
2230
  return {
2229
2231
  ok: true,
2230
- summary: "iui.config.ts repaired (removed assets tier bleed)"
2232
+ summary: "theme.config.ts repaired (removed assets tier bleed)"
2231
2233
  };
2232
2234
  }
2233
2235
  }
2234
2236
  }
2235
2237
  return {
2236
2238
  ok: false,
2237
- summary: "iui.config.ts violates three-config tier boundaries",
2239
+ summary: "theme.config.ts violates three-config tier boundaries",
2238
2240
  details: issues.map((i) => `- ${i}`).join("\n")
2239
2241
  };
2240
2242
  }
@@ -2528,12 +2530,6 @@ function mergeAssetSlotWithTemplate(slot, templateSlot) {
2528
2530
  function seedAssetsOutputFromTemplate(output) {
2529
2531
  const template = loadAssetsConfigTemplate();
2530
2532
  for (const [key, tplVal] of Object.entries(template)) {
2531
- if (key === "binding") {
2532
- if (output.binding === void 0 && tplVal !== void 0) {
2533
- output.binding = tplVal;
2534
- }
2535
- continue;
2536
- }
2537
2533
  if (typeof tplVal === "object" && tplVal !== null && !Array.isArray(tplVal)) {
2538
2534
  output[key] = mergeAssetSlotWithTemplate(
2539
2535
  output[key],
@@ -2541,13 +2537,6 @@ function seedAssetsOutputFromTemplate(output) {
2541
2537
  );
2542
2538
  }
2543
2539
  }
2544
- if (output.binding === "scanned") {
2545
- output.preload = output.preload ?? "scanned";
2546
- const icon = output.icon;
2547
- if (icon && typeof icon === "object" && !Array.isArray(icon)) {
2548
- icon.preload = icon.preload ?? "scanned";
2549
- }
2550
- }
2551
2540
  }
2552
2541
  function assetsConfigPath(cwd) {
2553
2542
  return path10.join(resolveIuiProjectRoot(cwd ?? process.cwd()), ASSETS_CONFIG_FILE);
@@ -2707,9 +2696,6 @@ function writeAssetsConfig(cwd = process.cwd()) {
2707
2696
  delete output[legacyKey];
2708
2697
  }
2709
2698
  }
2710
- if (output.binding === void 0 && Object.keys(assets2).length > 0 && projectHasViteTooling(cwd)) {
2711
- output.binding = "scanned";
2712
- }
2713
2699
  seedAssetsOutputFromTemplate(output);
2714
2700
  writeJson(assetsConfigPath(cwd), output);
2715
2701
  try {
@@ -2762,12 +2748,19 @@ function registryItemsMap(manifest) {
2762
2748
  }
2763
2749
  return map;
2764
2750
  }
2751
+ function resolveProjectConfigPath(root) {
2752
+ const current = path10.join(root, PROJECT_CONFIG_FILE);
2753
+ if (fs8.existsSync(current)) return current;
2754
+ const previous = path10.join(root, "iui.config.ts");
2755
+ if (fs8.existsSync(previous)) return previous;
2756
+ return current;
2757
+ }
2765
2758
  function writeProjectConfig(cwd = process.cwd()) {
2766
2759
  const configPath = path10.join(cwd, PROJECT_CONFIG_FILE);
2767
2760
  atomicWriteFile(configPath, buildProjectConfigSource(cwd));
2768
2761
  }
2769
2762
  function ensureProjectConfigBuildBlock(cwd = process.cwd()) {
2770
- const configPath = path10.join(resolveIuiProjectRoot(cwd), PROJECT_CONFIG_FILE);
2763
+ const configPath = resolveProjectConfigPath(resolveIuiProjectRoot(cwd));
2771
2764
  if (!fs8.existsSync(configPath)) return false;
2772
2765
  const before = fs8.readFileSync(configPath, "utf-8");
2773
2766
  const result = patchProjectConfigBuildBlock(before);
@@ -2777,7 +2770,7 @@ function ensureProjectConfigBuildBlock(cwd = process.cwd()) {
2777
2770
  }
2778
2771
  function ensureProjectConfig(cwd = process.cwd()) {
2779
2772
  const root = resolveIuiProjectRoot(cwd);
2780
- const configPath = path10.join(root, PROJECT_CONFIG_FILE);
2773
+ const configPath = resolveProjectConfigPath(root);
2781
2774
  if (!fs8.existsSync(configPath)) {
2782
2775
  writeProjectConfig(root);
2783
2776
  return "scaffolded";
@@ -2907,7 +2900,8 @@ function writeFlatProjectTsConfig(framework, cwd = process.cwd()) {
2907
2900
  }
2908
2901
  const include = Array.isArray(existing.include) ? [...existing.include.map(String)] : [];
2909
2902
  if (!include.includes("src")) include.push("src");
2910
- const rootConfigFiles = ["iui.config.ts", "component.config.ts"];
2903
+ const themeConfigFile = fs8.existsSync(path10.join(cwd, "iui.config.ts")) && !fs8.existsSync(path10.join(cwd, PROJECT_CONFIG_FILE)) ? "iui.config.ts" : PROJECT_CONFIG_FILE;
2904
+ const rootConfigFiles = [themeConfigFile, "component.config.ts"];
2911
2905
  for (const rootFile of rootConfigFiles) {
2912
2906
  if (!include.includes(rootFile)) include.push(rootFile);
2913
2907
  }
@@ -3371,13 +3365,13 @@ function ensureInventiveUiViteConfig(cwd = process.cwd()) {
3371
3365
  }
3372
3366
 
3373
3367
  // src/services/auth.ts
3374
- async function api(path28, opts) {
3375
- const res = await fetch(`${API_BASE_URL}${path28}`, {
3368
+ async function api(path27, opts) {
3369
+ const res = await fetch(`${API_BASE_URL}${path27}`, {
3376
3370
  ...opts,
3377
3371
  signal: opts?.signal ?? AbortSignal.timeout(API_REQUEST_TIMEOUT_MS),
3378
3372
  headers: { "Content-Type": "application/json", ...opts?.headers }
3379
3373
  });
3380
- throwIfRateLimited(res, `calling ${path28}`);
3374
+ throwIfRateLimited(res, `calling ${path27}`);
3381
3375
  if (!res.ok) {
3382
3376
  const body = await res.text().catch(() => "");
3383
3377
  throw new CLIError(`API error ${res.status}: ${body || res.statusText}`);
@@ -3629,10 +3623,12 @@ async function promptAssetSelection(installedPackages = []) {
3629
3623
  const choices = [];
3630
3624
  for (const cat of categories) {
3631
3625
  const inCategory = catalogue.filter((p) => p.category === cat);
3626
+ if (choices.length > 0) {
3627
+ choices.push(new inquirer.Separator(" "));
3628
+ }
3632
3629
  choices.push(
3633
3630
  new inquirer.Separator(
3634
- `
3635
- ${brand.bold(ASSET_CATEGORY_LABELS[cat])} ${dim(`(${inCategory.length})`)}`
3631
+ ` ${brand.bold(ASSET_CATEGORY_LABELS[cat])} ${dim(`(${inCategory.length})`)}`
3636
3632
  )
3637
3633
  );
3638
3634
  for (const pkg of inCategory) {
@@ -3644,6 +3640,8 @@ async function promptAssetSelection(installedPackages = []) {
3644
3640
  }
3645
3641
  }
3646
3642
  console.log();
3643
+ const terminalRows = process.stdout.rows ?? 0;
3644
+ const pageSize = terminalRows > 0 ? Math.max(10, Math.min(choices.length, terminalRows - 4)) : choices.length;
3647
3645
  const { selected } = await inquirer.prompt([
3648
3646
  {
3649
3647
  type: "checkbox",
@@ -3651,7 +3649,7 @@ async function promptAssetSelection(installedPackages = []) {
3651
3649
  message: chalk2.dim("Toggle packages to install"),
3652
3650
  prefix: PROMPT_PREFIX,
3653
3651
  choices,
3654
- pageSize: 20,
3652
+ pageSize,
3655
3653
  loop: false
3656
3654
  }
3657
3655
  ]);
@@ -3733,7 +3731,7 @@ async function promptChooseEmojiFamily(fallbackCurrent) {
3733
3731
  assertInteractivePrompt("emoji family choice");
3734
3732
  inputBox(
3735
3733
  "Emoji Family",
3736
- "Choose the default CDN style for emoji slots. Skin tone defaults to medium-light."
3734
+ "Choose the default CDN style for emoji slots. Skin tone defaults to medium-light (`mediumLight`)."
3737
3735
  );
3738
3736
  const { chosen } = await inquirer.prompt([
3739
3737
  {
@@ -3825,7 +3823,7 @@ async function promptText(title, hint2, placeholder, validate) {
3825
3823
  }
3826
3824
 
3827
3825
  // src/commands/init.ts
3828
- import path23 from "path";
3826
+ import path22 from "path";
3829
3827
  import ora3 from "ora";
3830
3828
 
3831
3829
  // src/services/license.ts
@@ -4792,8 +4790,8 @@ function getMajorFromVersion(version) {
4792
4790
  import ora2 from "ora";
4793
4791
 
4794
4792
  // src/services/slot-registry.ts
4795
- import fs18 from "fs-extra";
4796
- import path22 from "path";
4793
+ import fs17 from "fs-extra";
4794
+ import path21 from "path";
4797
4795
 
4798
4796
  // src/services/registry-lock.ts
4799
4797
  import fs11 from "fs";
@@ -4880,8 +4878,8 @@ async function withRegistryLock(cwd, operation) {
4880
4878
  }
4881
4879
 
4882
4880
  // src/services/slots.ts
4883
- import fs15 from "fs-extra";
4884
- import path19 from "path";
4881
+ import fs14 from "fs-extra";
4882
+ import path18 from "path";
4885
4883
 
4886
4884
  // src/utils/public-slot-contract.ts
4887
4885
  import path15 from "path";
@@ -5011,11 +5009,6 @@ function safeWriteFile(filePath, content) {
5011
5009
  atomicWriteFile(filePath, content);
5012
5010
  }
5013
5011
 
5014
- // src/services/asset-bound.ts
5015
- import fs14 from "fs-extra";
5016
- import path18 from "path";
5017
- import { pathToFileURL } from "url";
5018
-
5019
5012
  // src/services/generated-paths.ts
5020
5013
  import path17 from "path";
5021
5014
  function iuiProjectRoot2(cwd) {
@@ -5027,367 +5020,26 @@ function generatedIuiDir(cwd) {
5027
5020
  function generatedSlotsDir(cwd) {
5028
5021
  return path17.join(generatedIuiDir(cwd), "slots");
5029
5022
  }
5030
- function generatedAssetsDir(cwd) {
5031
- return path17.join(generatedIuiDir(cwd), "assets");
5032
- }
5033
-
5034
- // src/services/asset-bound.ts
5035
- var LIBRARY_TO_PKG = {
5036
- lucide: "icons-lucide",
5037
- phosphor: "icons-phosphor",
5038
- material: "icons-material",
5039
- "material-icons": "icons-material",
5040
- materialSymbols: "material-symbols",
5041
- "material-symbols": "material-symbols"
5042
- };
5043
- var PKG_LOOKUP_PREFIX = {
5044
- "icons-lucide": "icons/",
5045
- "icons-phosphor": "icons/",
5046
- "icons-material": "icons/",
5047
- "material-symbols": "icons/",
5048
- logos: "logos/",
5049
- "color-logos": "logos/",
5050
- flags: "flags/",
5051
- "file-types": "types/",
5052
- loaders: "loaders/",
5053
- illustrations: ""
5054
- };
5055
- var BOUND_SPECS = [
5056
- {
5057
- slotType: "icon",
5058
- fileName: "icons.bound.ts",
5059
- exportName: "BOUND_ICONS",
5060
- packages: /* @__PURE__ */ new Set([
5061
- "material-symbols",
5062
- "icons-lucide",
5063
- "icons-phosphor",
5064
- "icons-material"
5065
- ]),
5066
- filterByDefaultIconLibrary: true
5067
- },
5068
- {
5069
- slotType: "logo",
5070
- fileName: "logos.bound.ts",
5071
- exportName: "BOUND_LOGOS",
5072
- packages: /* @__PURE__ */ new Set(["logos"])
5073
- },
5074
- {
5075
- slotType: "color-logo",
5076
- fileName: "color-logos.bound.ts",
5077
- exportName: "BOUND_COLOR_LOGOS",
5078
- packages: /* @__PURE__ */ new Set(["color-logos"])
5079
- },
5080
- {
5081
- slotType: "flag",
5082
- fileName: "flags.bound.ts",
5083
- exportName: "BOUND_FLAGS",
5084
- packages: /* @__PURE__ */ new Set(["flags"])
5085
- },
5086
- {
5087
- slotType: "file-type",
5088
- fileName: "file-types.bound.ts",
5089
- exportName: "BOUND_FILE_TYPES",
5090
- packages: /* @__PURE__ */ new Set(["file-types"])
5091
- },
5092
- {
5093
- slotType: "loader",
5094
- fileName: "loaders.bound.ts",
5095
- exportName: "BOUND_LOADERS",
5096
- packages: /* @__PURE__ */ new Set(["loaders"])
5097
- },
5098
- {
5099
- slotType: "illustration",
5100
- fileName: "illustrations.bound.ts",
5101
- exportName: "BOUND_ILLUSTRATIONS",
5102
- packages: /* @__PURE__ */ new Set(["illustrations"])
5103
- }
5104
- ];
5105
- function isAssetPackageInstalled(cwd, pkgId) {
5106
- return resolvePackageDir(`@inventive-ui/${pkgId}`, cwd) !== null;
5107
- }
5108
- var DEFAULT_SCAN = {
5109
- scanDirs: ["src", ".storybook", "stories", ".iui"],
5110
- include: [
5111
- "**/*.stories.*",
5112
- "**/*.mdx",
5113
- "**/src/**/*.tsx",
5114
- "**/src/**/*.ts",
5115
- "**/src/**/*.jsx",
5116
- "**/src/**/*.js",
5117
- "**/.storybook/**/*.tsx",
5118
- "**/.storybook/**/*.ts",
5119
- "**/.storybook/**/*.jsx",
5120
- "**/.storybook/**/*.js"
5121
- ],
5122
- exclude: ["**/*.test.*", "**/*.spec.*"]
5123
- };
5124
- function resolveFrameworkModule(cwd, relativePath) {
5125
- const searchRoots = /* @__PURE__ */ new Set();
5126
- for (const candidate of [
5127
- resolveDependencyInstallRoot(cwd),
5128
- path18.resolve(cwd),
5129
- iuiProjectRoot2(cwd)
5130
- ]) {
5131
- searchRoots.add(path18.resolve(candidate));
5132
- }
5133
- for (const start of searchRoots) {
5134
- const frameworkDir = resolvePackageDir("@inventive-ui/framework", start);
5135
- if (!frameworkDir) continue;
5136
- const installed = path18.join(frameworkDir, relativePath);
5137
- if (fs14.existsSync(installed)) return installed;
5138
- }
5139
- const root = iuiProjectRoot2(cwd);
5140
- for (const candidate of [
5141
- path18.join(root, "..", "Framework", relativePath),
5142
- path18.join(root, "..", "..", "Framework", relativePath)
5143
- ]) {
5144
- if (fs14.existsSync(candidate)) return candidate;
5145
- }
5146
- return null;
5147
- }
5148
- async function loadScanUtils(cwd) {
5149
- const scanPath = resolveFrameworkModule(
5150
- cwd,
5151
- "integrations/vite/scan-used-slot-assets.mjs"
5152
- );
5153
- const resolvePath = resolveFrameworkModule(
5154
- cwd,
5155
- "integrations/shared/resolve-scanned-icon-name.mjs"
5156
- );
5157
- if (!scanPath || !resolvePath) {
5158
- const installRoot = resolveDependencyInstallRoot(cwd);
5159
- const frameworkDir = resolvePackageDir("@inventive-ui/framework", installRoot);
5160
- const hint2 = frameworkDir && !scanPath ? "Update @inventive-ui/framework to the latest version (iui update) \u2014 scan utilities require a current Framework release." : "Install @inventive-ui/framework and run iui doctor again.";
5161
- throw new CLIError("Could not load Framework scan utilities.", hint2);
5162
- }
5163
- const scanMod = await import(pathToFileURL(scanPath).href);
5164
- const resolveMod = await import(pathToFileURL(resolvePath).href);
5165
- return { ...scanMod, ...resolveMod };
5166
- }
5167
- function lookupKeyToGlyphKey(pkg, lookupKey) {
5168
- let subpath = lookupKey.replace(/^\.\//, "").replace(/\.js$/, "");
5169
- if (pkg === "illustrations") {
5170
- return subpath;
5171
- }
5172
- const prefix = PKG_LOOKUP_PREFIX[pkg];
5173
- if (prefix && subpath.startsWith(prefix)) {
5174
- subpath = subpath.slice(prefix.length);
5175
- }
5176
- return subpath;
5177
- }
5178
- function glyphToIdentifier(name, used) {
5179
- let base = name.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
5180
- if (!base || !/^[A-Za-z_$]/.test(base)) {
5181
- base = `Glyph${base}`;
5182
- }
5183
- let id = base;
5184
- let suffix = 2;
5185
- while (used.has(id)) {
5186
- id = `${base}${suffix++}`;
5187
- }
5188
- used.add(id);
5189
- return id;
5190
- }
5191
- function resolveIconPkg(library) {
5192
- return LIBRARY_TO_PKG[library] ?? library;
5193
- }
5194
- function buildBoundFileContent(exportName, entries) {
5195
- const lines = [
5196
- "// Managed by iui. Do not edit manually.",
5197
- '// Static glyph bindings for scanned assets (`binding: "scanned"`).',
5198
- "",
5199
- 'import type { ComponentType } from "react";'
5200
- ];
5201
- for (const entry of entries) {
5202
- lines.push(`import ${entry.identifier} from "${entry.moduleId}";`);
5203
- }
5204
- lines.push("");
5205
- lines.push(
5206
- `export const ${exportName}: Record<string, ComponentType<Record<string, unknown>>> = {`
5207
- );
5208
- for (const entry of entries) {
5209
- lines.push(` ${JSON.stringify(entry.key)}: ${entry.identifier},`);
5210
- }
5211
- lines.push("};");
5212
- lines.push("");
5213
- return lines.join("\n");
5214
- }
5215
- function cleanupAssetBoundFiles(cwd) {
5216
- const assetsDir = generatedAssetsDir(cwd);
5217
- if (!fs14.existsSync(assetsDir)) return;
5218
- for (const file of fs14.readdirSync(assetsDir)) {
5219
- if (file.endsWith(".bound.ts") || file === "register-bound.ts") {
5220
- fs14.removeSync(path18.join(assetsDir, file));
5221
- }
5222
- }
5223
- const remaining = fs14.readdirSync(assetsDir);
5224
- if (remaining.length === 0) {
5225
- fs14.removeSync(assetsDir);
5226
- }
5227
- }
5228
- function hasAssetBoundRegistration(cwd) {
5229
- return fs14.existsSync(path18.join(generatedAssetsDir(cwd), "register-bound.ts"));
5230
- }
5231
- async function writeAssetBoundFiles(cwd = process.cwd()) {
5232
- const root = iuiProjectRoot2(cwd);
5233
- const scanUtils = await loadScanUtils(cwd);
5234
- const activeSpecs = BOUND_SPECS.filter(
5235
- (spec) => scanUtils.isScannedAssetBindingEnabled(root, spec.slotType)
5236
- );
5237
- if (activeSpecs.length === 0) {
5238
- cleanupAssetBoundFiles(root);
5239
- return;
5240
- }
5241
- const registry = scanUtils.scanUsedSlotAssets(root, DEFAULT_SCAN);
5242
- const defaultIconLibrary = scanUtils.readDefaultIconLibraryFromConfig(root);
5243
- const defaultIconPkg = resolveIconPkg(defaultIconLibrary);
5244
- const assetsDir = generatedAssetsDir(root);
5245
- fs14.ensureDirSync(assetsDir);
5246
- const generatedFiles = /* @__PURE__ */ new Set();
5247
- const registrationSpecs = [];
5248
- for (const spec of activeSpecs) {
5249
- const entries = [];
5250
- const usedIdentifiers = /* @__PURE__ */ new Set();
5251
- for (const [pkg, keys] of registry.entries()) {
5252
- if (!spec.packages.has(pkg)) continue;
5253
- if ("filterByDefaultIconLibrary" in spec && spec.filterByDefaultIconLibrary && pkg !== defaultIconPkg) {
5254
- continue;
5255
- }
5256
- if (!isAssetPackageInstalled(cwd, pkg)) continue;
5257
- for (const lookupKey of keys) {
5258
- const key = lookupKeyToGlyphKey(pkg, lookupKey);
5259
- const moduleId = scanUtils.lookupKeyToModuleId(pkg, lookupKey);
5260
- const identifier = glyphToIdentifier(key, usedIdentifiers);
5261
- if (entries.some((entry) => entry.key === key)) continue;
5262
- entries.push({ key, moduleId, identifier });
5263
- }
5264
- }
5265
- entries.sort((a, b) => a.key.localeCompare(b.key));
5266
- if (entries.length === 0) {
5267
- continue;
5268
- }
5269
- const content = buildBoundFileContent(spec.exportName, entries);
5270
- const outPath = resolveWithinRoot(
5271
- root,
5272
- ".iui",
5273
- "generated",
5274
- "assets",
5275
- spec.fileName
5276
- );
5277
- safeWriteFile(outPath, content);
5278
- generatedFiles.add(spec.fileName);
5279
- registrationSpecs.push({
5280
- slotType: spec.slotType,
5281
- exportName: spec.exportName,
5282
- fileName: spec.fileName
5283
- });
5284
- }
5285
- const existing = fs14.existsSync(assetsDir) ? fs14.readdirSync(assetsDir).filter((f) => f.endsWith(".bound.ts")) : [];
5286
- for (const file of existing) {
5287
- if (!generatedFiles.has(file)) {
5288
- fs14.removeSync(path18.join(assetsDir, file));
5289
- }
5290
- }
5291
- if (registrationSpecs.length === 0) {
5292
- cleanupAssetBoundFiles(root);
5293
- return;
5294
- }
5295
- const registerLines = [
5296
- "// Managed by iui. Do not edit manually.",
5297
- "",
5298
- 'import { registerBoundAssetComponents } from "@inventive-ui/framework/slots";'
5299
- ];
5300
- for (const spec of registrationSpecs) {
5301
- registerLines.push(
5302
- `import { ${spec.exportName} } from "./${spec.fileName.replace(/\.ts$/, "")}";`
5303
- );
5304
- }
5305
- registerLines.push("");
5306
- for (const spec of registrationSpecs) {
5307
- registerLines.push(
5308
- `registerBoundAssetComponents(${JSON.stringify(spec.slotType)}, ${spec.exportName});`
5309
- );
5310
- }
5311
- registerLines.push("");
5312
- safeWriteFile(
5313
- resolveWithinRoot(root, ".iui", "generated", "assets", "register-bound.ts"),
5314
- registerLines.join("\n")
5315
- );
5316
- }
5317
- function assetModuleCandidates(pkgRoot, moduleId) {
5318
- const pkgName = moduleId.split("/").slice(0, 2).join("/");
5319
- const subpath = moduleId.slice(pkgName.length + 1);
5320
- const pkgId = pkgName.replace("@inventive-ui/", "");
5321
- if (!subpath || subpath.includes("..")) return [];
5322
- if (pkgId === "loaders") {
5323
- return [path18.join(pkgRoot, "dist", "loaders", `${subpath}.js`)];
5324
- }
5325
- if (pkgId === "illustrations") {
5326
- const [family, scene] = subpath.split("/");
5327
- if (family && scene) {
5328
- return [path18.join(pkgRoot, "dist", family, `${scene}.js`)];
5329
- }
5330
- return [path18.join(pkgRoot, "dist", `${subpath}.js`)];
5331
- }
5332
- const prefix = PKG_LOOKUP_PREFIX[pkgId];
5333
- if (prefix) {
5334
- const dir = prefix.replace(/\/$/, "");
5335
- return [
5336
- path18.join(pkgRoot, "dist", dir, `${subpath}.js`),
5337
- path18.join(pkgRoot, "dist", `${subpath}.js`),
5338
- path18.join(pkgRoot, "dist", subpath, "index.js")
5339
- ];
5340
- }
5341
- return [
5342
- path18.join(pkgRoot, "dist", `${subpath}.js`),
5343
- path18.join(pkgRoot, "dist", subpath, "index.js")
5344
- ];
5345
- }
5346
- function validateGeneratedAssetBoundImports(cwd = process.cwd()) {
5347
- const assetsDir = generatedAssetsDir(cwd);
5348
- if (!fs14.existsSync(assetsDir)) return [];
5349
- const issues = [];
5350
- const boundFiles = fs14.readdirSync(assetsDir).filter((file) => file.endsWith(".bound.ts"));
5351
- for (const file of boundFiles) {
5352
- const content = fs14.readFileSync(path18.join(assetsDir, file), "utf8");
5353
- const importRe = /from\s+["'](@inventive-ui\/[^"']+)["']/g;
5354
- let match;
5355
- while ((match = importRe.exec(content)) !== null) {
5356
- const moduleId = match[1];
5357
- const pkgName = moduleId.split("/").slice(0, 2).join("/");
5358
- const pkgRoot = resolvePackageDir(pkgName, cwd);
5359
- if (!pkgRoot) {
5360
- issues.push(`${file}: missing asset package ${pkgName}`);
5361
- continue;
5362
- }
5363
- const candidates = assetModuleCandidates(pkgRoot, moduleId);
5364
- if (!candidates.some((candidate) => fs14.existsSync(candidate))) {
5365
- issues.push(`${file}: missing asset module ${moduleId}`);
5366
- }
5367
- }
5368
- }
5369
- return issues;
5370
- }
5371
5023
 
5372
5024
  // src/services/slots.ts
5373
5025
  var SLOT_GROUP_CORE_FILE = "slot-core.generated.tsx";
5374
5026
  var SLOT_GROUP_OPTIONAL_FILE = "slot-optional.generated.tsx";
5375
5027
  function bridgeSlotFilePath(cwd) {
5376
- return path19.join(cwd, "src", "iui", "slot.tsx");
5028
+ return path18.join(cwd, "src", "iui", "slot.tsx");
5377
5029
  }
5378
5030
  function cleanupLegacySourceSlotFiles(cwd) {
5379
- const legacySlotsDir = path19.join(cwd, "src", "iui", "slots");
5380
- if (!fs15.existsSync(legacySlotsDir)) return;
5031
+ const legacySlotsDir = path18.join(cwd, "src", "iui", "slots");
5032
+ if (!fs14.existsSync(legacySlotsDir)) return;
5381
5033
  try {
5382
- const files = fs15.readdirSync(legacySlotsDir);
5034
+ const files = fs14.readdirSync(legacySlotsDir);
5383
5035
  for (const file of files) {
5384
5036
  if (file.endsWith(".slot.tsx")) {
5385
- fs15.removeSync(path19.join(legacySlotsDir, file));
5037
+ fs14.removeSync(path18.join(legacySlotsDir, file));
5386
5038
  }
5387
5039
  }
5388
- const remaining = fs15.readdirSync(legacySlotsDir);
5040
+ const remaining = fs14.readdirSync(legacySlotsDir);
5389
5041
  if (remaining.length === 0) {
5390
- fs15.removeSync(legacySlotsDir);
5042
+ fs14.removeSync(legacySlotsDir);
5391
5043
  }
5392
5044
  } catch {
5393
5045
  }
@@ -5451,18 +5103,18 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
5451
5103
  const generationIssues = [];
5452
5104
  cleanupLegacySourceSlotFiles(cwd);
5453
5105
  if (Object.keys(components).length === 0) {
5454
- if (fs15.existsSync(slotsDir)) {
5455
- const existingSlots2 = fs15.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx"));
5106
+ if (fs14.existsSync(slotsDir)) {
5107
+ const existingSlots2 = fs14.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx"));
5456
5108
  for (const file of existingSlots2) {
5457
5109
  try {
5458
- fs15.removeSync(path19.join(slotsDir, file));
5110
+ fs14.removeSync(path18.join(slotsDir, file));
5459
5111
  } catch {
5460
5112
  }
5461
5113
  }
5462
5114
  }
5463
5115
  return;
5464
5116
  }
5465
- fs15.ensureDirSync(slotsDir);
5117
+ fs14.ensureDirSync(slotsDir);
5466
5118
  if (!pkgManifest) return;
5467
5119
  const itemsLookup = registryItemsMap(pkgManifest);
5468
5120
  const installedItems = Object.entries(components).map(([slug]) => itemsLookup[slug]).filter((item) => Boolean(item));
@@ -5503,7 +5155,7 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
5503
5155
  for (const group of renderedGroups) {
5504
5156
  const outPath = resolveWithinRoot(root, ".iui", "generated", "slots", group.fileName);
5505
5157
  if (group.emitters.length === 0) {
5506
- if (fs15.existsSync(outPath)) fs15.removeSync(outPath);
5158
+ if (fs14.existsSync(outPath)) fs14.removeSync(outPath);
5507
5159
  continue;
5508
5160
  }
5509
5161
  safeWriteFile(
@@ -5513,19 +5165,19 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
5513
5165
  })
5514
5166
  );
5515
5167
  }
5516
- const existingSlots = fs15.existsSync(slotsDir) ? fs15.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx") || f.endsWith(".generated.tsx")) : [];
5168
+ const existingSlots = fs14.existsSync(slotsDir) ? fs14.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx") || f.endsWith(".generated.tsx")) : [];
5517
5169
  for (const file of existingSlots) {
5518
5170
  if (file === SLOT_GROUP_CORE_FILE || file === SLOT_GROUP_OPTIONAL_FILE) continue;
5519
5171
  if (file.endsWith(".slot.tsx")) {
5520
5172
  try {
5521
- fs15.removeSync(path19.join(slotsDir, file));
5173
+ fs14.removeSync(path18.join(slotsDir, file));
5522
5174
  } catch {
5523
5175
  }
5524
5176
  continue;
5525
5177
  }
5526
5178
  if (file.endsWith(".generated.tsx")) {
5527
5179
  try {
5528
- fs15.removeSync(path19.join(slotsDir, file));
5180
+ fs14.removeSync(path18.join(slotsDir, file));
5529
5181
  } catch {
5530
5182
  }
5531
5183
  }
@@ -5629,24 +5281,18 @@ function writeSlotHelperFile(cwd = process.cwd()) {
5629
5281
  }
5630
5282
  const typesArray = Array.from(slotTypes).sort();
5631
5283
  const slotImports = [];
5632
- const coreSlotsPath = path19.join(generatedSlotsDir(cwd), SLOT_GROUP_CORE_FILE);
5633
- const optionalSlotsPath = path19.join(generatedSlotsDir(cwd), SLOT_GROUP_OPTIONAL_FILE);
5634
- if (fs15.existsSync(coreSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_CORE_FILE.replace(/\.tsx$/, "")}";`);
5635
- if (fs15.existsSync(optionalSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_OPTIONAL_FILE.replace(/\.tsx$/, "")}";`);
5284
+ const coreSlotsPath = path18.join(generatedSlotsDir(cwd), SLOT_GROUP_CORE_FILE);
5285
+ const optionalSlotsPath = path18.join(generatedSlotsDir(cwd), SLOT_GROUP_OPTIONAL_FILE);
5286
+ if (fs14.existsSync(coreSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_CORE_FILE.replace(/\.tsx$/, "")}";`);
5287
+ if (fs14.existsSync(optionalSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_OPTIONAL_FILE.replace(/\.tsx$/, "")}";`);
5636
5288
  const componentSlotImports = slotImports.join("\n");
5637
- const includeAssetBindings = hasAssetBoundRegistration(cwd);
5638
5289
  const outDir = generatedIuiDir(cwd);
5639
- fs15.ensureDirSync(outDir);
5640
- const outPath = path19.join(outDir, "slot.generated.tsx");
5290
+ fs14.ensureDirSync(outDir);
5291
+ const outPath = path18.join(outDir, "slot.generated.tsx");
5641
5292
  const sections = [
5642
5293
  `// Managed by iui. Do not edit manually.`,
5643
5294
  `// Rebuilt automatically when the CLI validates the project.`
5644
5295
  ];
5645
- if (includeAssetBindings) {
5646
- sections.push("");
5647
- sections.push("// Scanned asset bindings (static glyph imports)");
5648
- sections.push(`import "./assets/register-bound";`);
5649
- }
5650
5296
  if (componentSlotImports) {
5651
5297
  sections.push("");
5652
5298
  sections.push("// Component slot registrations");
@@ -5672,11 +5318,11 @@ ${typesArray.map((t) => ` | "${t}"`).join("\n")};` : `export type IUISlotType =
5672
5318
  }
5673
5319
  function writeSlotBridge(packageDir, iuiRoot2) {
5674
5320
  const bridgePath = bridgeSlotFilePath(packageDir);
5675
- const generatedFile = path19.join(iuiRoot2, ".iui", "generated", "slot.generated.tsx");
5676
- const importBase = relativeImportPath(path19.dirname(bridgePath), generatedFile);
5677
- fs15.ensureDirSync(path19.dirname(bridgePath));
5678
- if (fs15.existsSync(bridgePath)) {
5679
- const existing = fs15.readFileSync(bridgePath, "utf-8");
5321
+ const generatedFile = path18.join(iuiRoot2, ".iui", "generated", "slot.generated.tsx");
5322
+ const importBase = relativeImportPath(path18.dirname(bridgePath), generatedFile);
5323
+ fs14.ensureDirSync(path18.dirname(bridgePath));
5324
+ if (fs14.existsSync(bridgePath)) {
5325
+ const existing = fs14.readFileSync(bridgePath, "utf-8");
5680
5326
  if (existing.length > 0 && !/@iui-managed/.test(existing)) {
5681
5327
  return;
5682
5328
  }
@@ -5693,18 +5339,18 @@ export type { IUISlotType } from "${importBase}";
5693
5339
  }
5694
5340
 
5695
5341
  // src/services/workspace-bootstrap.ts
5696
- import path21 from "path";
5697
- import fs17 from "fs-extra";
5342
+ import path20 from "path";
5343
+ import fs16 from "fs-extra";
5698
5344
 
5699
5345
  // src/services/bootstrap.ts
5700
- import fs16 from "fs-extra";
5701
- import path20 from "path";
5346
+ import fs15 from "fs-extra";
5347
+ import path19 from "path";
5702
5348
  var BOOTSTRAP_GENERATED_FILE = "bootstrap.generated.tsx";
5703
5349
  function bridgeBootstrapFilePath(cwd) {
5704
- return path20.join(cwd, "src", "iui", "bootstrap.ts");
5350
+ return path19.join(cwd, "src", "iui", "bootstrap.ts");
5705
5351
  }
5706
5352
  function bootstrapGeneratedPath(cwd = process.cwd()) {
5707
- return path20.join(generatedIuiDir(cwd), BOOTSTRAP_GENERATED_FILE);
5353
+ return path19.join(generatedIuiDir(cwd), BOOTSTRAP_GENERATED_FILE);
5708
5354
  }
5709
5355
  function resolveProjectConfigPaths(cwd) {
5710
5356
  const meta = readProjectMeta(cwd);
@@ -5719,8 +5365,8 @@ function resolveProjectConfigPaths(cwd) {
5719
5365
  };
5720
5366
  }
5721
5367
  function configImportFromGenerated(cwd, configRel) {
5722
- const generatedDir = path20.dirname(bootstrapGeneratedPath(cwd));
5723
- const abs = path20.resolve(cwd, configRel.replace(/^\.\//, ""));
5368
+ const generatedDir = path19.dirname(bootstrapGeneratedPath(cwd));
5369
+ const abs = path19.resolve(cwd, configRel.replace(/^\.\//, ""));
5724
5370
  return relativeImportPath(generatedDir, abs);
5725
5371
  }
5726
5372
  function expectedBootstrapImportPaths(cwd) {
@@ -5733,13 +5379,13 @@ function expectedBootstrapImportPaths(cwd) {
5733
5379
  }
5734
5380
  function writeBootstrapGenerated(cwd = process.cwd()) {
5735
5381
  const outPath = bootstrapGeneratedPath(cwd);
5736
- fs16.ensureDirSync(path20.dirname(outPath));
5382
+ fs15.ensureDirSync(path19.dirname(outPath));
5737
5383
  const imports = expectedBootstrapImportPaths(cwd);
5738
5384
  const content = `// @iui-managed
5739
5385
 
5740
5386
  // Generated by iui CLI \u2014 do not edit manually.
5741
5387
 
5742
- // Connects iui.config.ts + assets.config.json + component.config.ts for standard bootstrap.
5388
+ // Connects theme.config.ts + assets.config.json + component.config.ts for standard bootstrap.
5743
5389
 
5744
5390
 
5745
5391
 
@@ -5759,7 +5405,7 @@ import {
5759
5405
 
5760
5406
  } from "@inventive-ui/framework";
5761
5407
 
5762
- import { initConfig as initSlotsConfig } from "@inventive-ui/framework/slots";
5408
+ import { initConfig as initAssetsConfig } from "@inventive-ui/framework/assets";
5763
5409
 
5764
5410
  import type { IUIAssetsConfig } from "@inventive-ui/framework/config";
5765
5411
 
@@ -5795,7 +5441,7 @@ registerBootstrapState({
5795
5441
 
5796
5442
  initFramework(frameworkConfig);
5797
5443
 
5798
- initSlotsConfig(frameworkConfig);
5444
+ initAssetsConfig(frameworkConfig);
5799
5445
 
5800
5446
 
5801
5447
 
@@ -5807,10 +5453,10 @@ export { projectComponentConfig as componentConfig };
5807
5453
  function writeBootstrapBridge(packageDir, iuiRoot2) {
5808
5454
  const bridgePath = bridgeBootstrapFilePath(packageDir);
5809
5455
  const generatedFile = bootstrapGeneratedPath(iuiRoot2);
5810
- const importBase = relativeImportPath(path20.dirname(bridgePath), generatedFile);
5811
- fs16.ensureDirSync(path20.dirname(bridgePath));
5812
- if (fs16.existsSync(bridgePath)) {
5813
- const existing = fs16.readFileSync(bridgePath, "utf-8");
5456
+ const importBase = relativeImportPath(path19.dirname(bridgePath), generatedFile);
5457
+ fs15.ensureDirSync(path19.dirname(bridgePath));
5458
+ if (fs15.existsSync(bridgePath)) {
5459
+ const existing = fs15.readFileSync(bridgePath, "utf-8");
5814
5460
  if (existing.length > 0 && !/@iui-managed/.test(existing)) {
5815
5461
  return;
5816
5462
  }
@@ -5835,13 +5481,13 @@ function writeProjectBootstrapArtifacts(packageDir, iuiRoot2) {
5835
5481
 
5836
5482
  // src/services/workspace-bootstrap.ts
5837
5483
  function workspaceManifestPath(iuiRoot2) {
5838
- return path21.join(iuiRoot2, IUI_DIR, "workspace.json");
5484
+ return path20.join(iuiRoot2, IUI_DIR, "workspace.json");
5839
5485
  }
5840
5486
  function readWorkspaceManifest(iuiRoot2) {
5841
5487
  const p = workspaceManifestPath(iuiRoot2);
5842
- if (!fs17.existsSync(p)) return null;
5488
+ if (!fs16.existsSync(p)) return null;
5843
5489
  try {
5844
- const raw = fs17.readJsonSync(p);
5490
+ const raw = fs16.readJsonSync(p);
5845
5491
  if (!Array.isArray(raw.packages)) return null;
5846
5492
  return {
5847
5493
  iuiRoot: raw.iuiRoot ?? iuiRoot2,
@@ -5853,40 +5499,40 @@ function readWorkspaceManifest(iuiRoot2) {
5853
5499
  }
5854
5500
  }
5855
5501
  function writeWorkspaceManifest(iuiRoot2, packageDirs) {
5856
- const unique = [...new Set(packageDirs.map((dir) => path21.resolve(dir)))];
5502
+ const unique = [...new Set(packageDirs.map((dir) => path20.resolve(dir)))];
5857
5503
  atomicWriteJson(workspaceManifestPath(iuiRoot2), {
5858
- packages: unique.map((dir) => path21.relative(iuiRoot2, dir) || "."),
5504
+ packages: unique.map((dir) => path20.relative(iuiRoot2, dir) || "."),
5859
5505
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
5860
5506
  });
5861
5507
  }
5862
5508
  function resolveRegisteredPackageDirs(iuiRoot2) {
5863
- const resolvedRoot = path21.resolve(iuiRoot2);
5509
+ const resolvedRoot = path20.resolve(iuiRoot2);
5864
5510
  const manifest = readWorkspaceManifest(resolvedRoot);
5865
5511
  if (!manifest) return [resolvedRoot];
5866
5512
  const dirs = manifest.packages.map(
5867
- (rel) => path21.resolve(resolvedRoot, rel === "." ? "" : rel)
5513
+ (rel) => path20.resolve(resolvedRoot, rel === "." ? "" : rel)
5868
5514
  );
5869
- if (!dirs.some((dir) => path21.resolve(dir) === resolvedRoot)) {
5515
+ if (!dirs.some((dir) => path20.resolve(dir) === resolvedRoot)) {
5870
5516
  dirs.unshift(resolvedRoot);
5871
5517
  }
5872
5518
  return dirs;
5873
5519
  }
5874
5520
  function registerWorkspacePackage(iuiRoot2, packageDir) {
5875
- const resolvedRoot = path21.resolve(iuiRoot2);
5876
- const resolvedPackage = path21.resolve(packageDir);
5521
+ const resolvedRoot = path20.resolve(iuiRoot2);
5522
+ const resolvedPackage = path20.resolve(packageDir);
5877
5523
  const existing = resolveRegisteredPackageDirs(resolvedRoot);
5878
- if (!existing.some((dir) => path21.resolve(dir) === resolvedPackage)) {
5524
+ if (!existing.some((dir) => path20.resolve(dir) === resolvedPackage)) {
5879
5525
  existing.push(resolvedPackage);
5880
5526
  }
5881
5527
  writeWorkspaceManifest(resolvedRoot, existing);
5882
5528
  }
5883
5529
  function registerAllWorkspacePackages(iuiRoot2) {
5884
- const resolvedRoot = path21.resolve(iuiRoot2);
5530
+ const resolvedRoot = path20.resolve(iuiRoot2);
5885
5531
  const workspaceRoot = findWorkspaceRoot(resolvedRoot);
5886
5532
  const targets = /* @__PURE__ */ new Set([resolvedRoot]);
5887
5533
  if (workspaceRoot) {
5888
5534
  for (const pkgDir of listWorkspacePackageDirs(workspaceRoot)) {
5889
- targets.add(path21.resolve(pkgDir));
5535
+ targets.add(path20.resolve(pkgDir));
5890
5536
  }
5891
5537
  }
5892
5538
  const dirs = [...targets];
@@ -5897,7 +5543,7 @@ function bootstrapRegisteredPackages(iuiRoot2) {
5897
5543
  const resolvedRoot = resolveIuiProjectRoot(iuiRoot2);
5898
5544
  const bootstrapped = [];
5899
5545
  for (const packageDir of resolveRegisteredPackageDirs(resolvedRoot)) {
5900
- if (!fs17.existsSync(path21.join(packageDir, "package.json"))) continue;
5546
+ if (!fs16.existsSync(path20.join(packageDir, "package.json"))) continue;
5901
5547
  ensureProjectNpmrc(packageDir);
5902
5548
  writeSlotBridge(packageDir, resolvedRoot);
5903
5549
  writeProjectBootstrapArtifacts(packageDir, resolvedRoot);
@@ -5906,9 +5552,9 @@ function bootstrapRegisteredPackages(iuiRoot2) {
5906
5552
  return bootstrapped;
5907
5553
  }
5908
5554
  async function bootstrapWorkspacePackage(packageDir, iuiRoot2) {
5909
- const resolvedPackage = path21.resolve(packageDir);
5555
+ const resolvedPackage = path20.resolve(packageDir);
5910
5556
  const resolvedIuiRoot = resolveIuiProjectRoot(iuiRoot2);
5911
- if (!fs17.existsSync(path21.join(resolvedPackage, "package.json"))) {
5557
+ if (!fs16.existsSync(path20.join(resolvedPackage, "package.json"))) {
5912
5558
  throw new CLIError(
5913
5559
  `No package.json found in ${resolvedPackage}.`,
5914
5560
  "Run iui init from a workspace app directory that contains package.json."
@@ -5944,17 +5590,17 @@ function checksumFor(components, slots) {
5944
5590
  return sha256(JSON.stringify({ components, slots }));
5945
5591
  }
5946
5592
  function backupCorruptFile(filePath) {
5947
- if (!fs18.existsSync(filePath)) return;
5593
+ if (!fs17.existsSync(filePath)) return;
5948
5594
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5949
5595
  try {
5950
- fs18.moveSync(filePath, `${filePath}.corrupt-${stamp}`, { overwrite: false });
5596
+ fs17.moveSync(filePath, `${filePath}.corrupt-${stamp}`, { overwrite: false });
5951
5597
  } catch {
5952
5598
  }
5953
5599
  }
5954
5600
  function readJsonObject(filePath, fallback, issues, label) {
5955
- if (!fs18.existsSync(filePath)) return fallback;
5601
+ if (!fs17.existsSync(filePath)) return fallback;
5956
5602
  try {
5957
- const value = fs18.readJsonSync(filePath);
5603
+ const value = fs17.readJsonSync(filePath);
5958
5604
  if (value && typeof value === "object" && !Array.isArray(value)) {
5959
5605
  return value;
5960
5606
  }
@@ -5966,9 +5612,9 @@ function readJsonObject(filePath, fallback, issues, label) {
5966
5612
  }
5967
5613
  function readState(cwd, issues) {
5968
5614
  const filePath = statePath(cwd);
5969
- if (!fs18.existsSync(filePath)) return null;
5615
+ if (!fs17.existsSync(filePath)) return null;
5970
5616
  try {
5971
- const raw = fs18.readJsonSync(filePath);
5617
+ const raw = fs17.readJsonSync(filePath);
5972
5618
  if (raw.schemaVersion !== STATE_SCHEMA_VERSION) {
5973
5619
  issues.push("registration state schema was upgraded");
5974
5620
  return null;
@@ -6072,7 +5718,7 @@ async function ensureSlotRegistry(options = {}) {
6072
5718
  }
6073
5719
  const iuiRoot2 = resolveIuiProjectRoot(cwd);
6074
5720
  return withRegistryLock(iuiRoot2, async () => {
6075
- const iuiPath = path22.join(iuiRoot2, IUI_DIR);
5721
+ const iuiPath = path21.join(iuiRoot2, IUI_DIR);
6076
5722
  const issues = [];
6077
5723
  cleanupTempFiles(iuiPath);
6078
5724
  const registry = ensureInstalledManifest(
@@ -6126,9 +5772,7 @@ async function ensureSlotRegistry(options = {}) {
6126
5772
  if (driftDetected) {
6127
5773
  issues.push("slot manifests drifted");
6128
5774
  }
6129
- const generationIssues = validateGeneratedSlotImports(iuiRoot2);
6130
- const assetBoundIssues = validateGeneratedAssetBoundImports(iuiRoot2);
6131
- const integrityIssues = [...generationIssues, ...assetBoundIssues];
5775
+ const integrityIssues = validateGeneratedSlotImports(iuiRoot2);
6132
5776
  if (shouldSkipWritesFastPath({
6133
5777
  mode,
6134
5778
  previousState,
@@ -6182,7 +5826,6 @@ async function ensureSlotRegistry(options = {}) {
6182
5826
  writeComponentSlotFiles(iuiRoot2);
6183
5827
  writeAssetsConfig(iuiRoot2);
6184
5828
  ensureProjectConfig(iuiRoot2);
6185
- await writeAssetBoundFiles(iuiRoot2);
6186
5829
  writeSlotHelperFile(iuiRoot2);
6187
5830
  if (projectHasViteTooling(cwd)) {
6188
5831
  ensureInventiveUiViteConfig(cwd);
@@ -6367,7 +6010,7 @@ async function initCommand(opts) {
6367
6010
  try {
6368
6011
  heading("Initialize Project");
6369
6012
  const existingIuiRoot = findIuiProjectRoot(invocationCwd);
6370
- if (existingIuiRoot && path23.resolve(existingIuiRoot) !== path23.resolve(invocationCwd)) {
6013
+ if (existingIuiRoot && path22.resolve(existingIuiRoot) !== path22.resolve(invocationCwd)) {
6371
6014
  await bootstrapWorkspacePackage(invocationCwd, existingIuiRoot);
6372
6015
  return;
6373
6016
  }
@@ -6386,10 +6029,10 @@ async function initCommand(opts) {
6386
6029
  return;
6387
6030
  }
6388
6031
  const originalCwd = process.cwd();
6389
- if (path23.resolve(initRoot) !== path23.resolve(originalCwd)) {
6032
+ if (path22.resolve(initRoot) !== path22.resolve(originalCwd)) {
6390
6033
  process.chdir(initRoot);
6391
6034
  hint(
6392
- `Monorepo --workspace: initializing at ${path23.relative(invocationCwd, initRoot) || initRoot}`
6035
+ `Monorepo --workspace: initializing at ${path22.relative(invocationCwd, initRoot) || initRoot}`
6393
6036
  );
6394
6037
  } else if (!sharedWorkspace && findIuiProjectRoot(initRoot) === null) {
6395
6038
  hint("Initializing this package only \u2014 other monorepo apps are untouched.");
@@ -6450,7 +6093,7 @@ async function initCommand(opts) {
6450
6093
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
6451
6094
  initScope: sharedWorkspace ? "workspace" : "package",
6452
6095
  configs: {
6453
- theme: "./iui.config.ts",
6096
+ theme: "./theme.config.ts",
6454
6097
  assets: "./assets.config.json",
6455
6098
  components: "./component.config.ts"
6456
6099
  }
@@ -6514,12 +6157,12 @@ async function initCommand(opts) {
6514
6157
  ensureTsConfigForIui(framework.framework, initRoot);
6515
6158
  if (framework.framework === "vite") {
6516
6159
  ensureInventiveUiViteConfig(initRoot);
6517
- ok("Config files ready (iui.config.ts, tsconfig.json, tsconfig.node.json, vite.config.ts)");
6160
+ ok("Config files ready (theme.config.ts, tsconfig.json, tsconfig.node.json, vite.config.ts)");
6518
6161
  } else {
6519
6162
  if (removeStaleIuiViteConfig(initRoot)) {
6520
6163
  hint("Removed vite.config.ts (React-only preset \u2014 no Vite tooling required).");
6521
6164
  }
6522
- ok("Config files ready (iui.config.ts, tsconfig.json)");
6165
+ ok("Config files ready (theme.config.ts, tsconfig.json)");
6523
6166
  }
6524
6167
  step("Scaffolding component.config.ts\u2026");
6525
6168
  const fetchedRegistry = await fetchComponentRegistry(auth.token);
@@ -7272,17 +6915,17 @@ async function deployTokenRevokeCommand(tokenId) {
7272
6915
  }
7273
6916
 
7274
6917
  // src/commands/setup.ts
7275
- import path26 from "path";
7276
- import fs20 from "fs-extra";
6918
+ import path25 from "path";
6919
+ import fs19 from "fs-extra";
7277
6920
  import ora6 from "ora";
7278
6921
 
7279
6922
  // src/commands/doctor.ts
7280
- import path25 from "path";
6923
+ import path24 from "path";
7281
6924
 
7282
6925
  // src/services/health.ts
7283
6926
  import { execFileSync as execFileSync2 } from "child_process";
7284
- import path24 from "path";
7285
- import fs19 from "fs-extra";
6927
+ import path23 from "path";
6928
+ import fs18 from "fs-extra";
7286
6929
  function installDevTypeScript(cwd) {
7287
6930
  const pm = detectPackageManager(cwd);
7288
6931
  try {
@@ -7325,8 +6968,8 @@ function checkGeneratedSlotValidity(cwd = process.cwd()) {
7325
6968
  };
7326
6969
  }
7327
6970
  function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
7328
- const configPath = path24.join(cwd, COMPONENT_CONFIG_FILE);
7329
- if (!fs19.existsSync(configPath)) {
6971
+ const configPath = path23.join(cwd, COMPONENT_CONFIG_FILE);
6972
+ if (!fs18.existsSync(configPath)) {
7330
6973
  return {
7331
6974
  ok: false,
7332
6975
  summary: "component.config.ts not found",
@@ -7334,8 +6977,8 @@ function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
7334
6977
  };
7335
6978
  }
7336
6979
  const tsPkgDir = resolvePackageDir("typescript", cwd);
7337
- const tscPath = tsPkgDir ? path24.join(tsPkgDir, "bin", "tsc") : path24.join(cwd, "node_modules", "typescript", "bin", "tsc");
7338
- if (!fs19.existsSync(tscPath)) {
6980
+ const tscPath = tsPkgDir ? path23.join(tsPkgDir, "bin", "tsc") : path23.join(cwd, "node_modules", "typescript", "bin", "tsc");
6981
+ if (!fs18.existsSync(tscPath)) {
7339
6982
  if (!options.autoFix) {
7340
6983
  return {
7341
6984
  ok: false,
@@ -7403,33 +7046,36 @@ ${stderr}`.trim() };
7403
7046
  function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7404
7047
  const warnings = [];
7405
7048
  const hints = [];
7406
- const configPath = path24.join(cwd, PROJECT_CONFIG_FILE);
7407
- if (fs19.existsSync(configPath)) {
7408
- const configContent = fs19.readFileSync(configPath, "utf-8");
7049
+ const configPath = path23.join(
7050
+ cwd,
7051
+ fs18.existsSync(path23.join(cwd, PROJECT_CONFIG_FILE)) || !fs18.existsSync(path23.join(cwd, "iui.config.ts")) ? PROJECT_CONFIG_FILE : "iui.config.ts"
7052
+ );
7053
+ if (fs18.existsSync(configPath)) {
7054
+ const configContent = fs18.readFileSync(configPath, "utf-8");
7409
7055
  if (/packageSafelist\s*:\s*false/.test(configContent)) {
7410
7056
  warnings.push(
7411
- "Deprecated iui.config build.packageSafelist \u2014 remove it; Framework always merges IUI package compile contracts"
7057
+ "Deprecated theme.config build.packageSafelist \u2014 remove it; Framework always merges IUI package compile contracts"
7412
7058
  );
7413
7059
  }
7414
7060
  if (/includeShadeMatrix\s*:/.test(configContent)) {
7415
7061
  warnings.push(
7416
- "Deprecated compiler flags in iui.config build.* \u2014 remove them; compile policy is Framework-internal"
7062
+ "Deprecated compiler flags in theme.config build.* \u2014 remove them; compile policy is Framework-internal"
7417
7063
  );
7418
7064
  hints.push("Use theme + optional scan.dirs only. See Framework docs/01-compile-first-guide.md");
7419
7065
  }
7420
7066
  if (/scanPackages\s*:/.test(configContent) || /scan\.packages\s*:/.test(configContent)) {
7421
7067
  warnings.push(
7422
- "Deprecated scanPackages in iui.config \u2014 IUI packages are discovered from package.json dependencies"
7068
+ "Deprecated scanPackages in theme.config \u2014 IUI packages are discovered from package.json dependencies"
7423
7069
  );
7424
7070
  }
7425
7071
  }
7426
7072
  if (projectHasViteTooling(cwd)) {
7427
7073
  const viteCandidates = ["vite.config.ts", "vite.config.mjs", "vite.config.js"];
7428
- const vitePath = viteCandidates.map((name) => path24.join(cwd, name)).find((p) => fs19.existsSync(p));
7074
+ const vitePath = viteCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
7429
7075
  if (!vitePath) {
7430
7076
  warnings.push("Vite tooling detected but no vite.config.* found");
7431
7077
  } else {
7432
- const viteContent = fs19.readFileSync(vitePath, "utf-8");
7078
+ const viteContent = fs18.readFileSync(vitePath, "utf-8");
7433
7079
  if (!/inventiveUiVite\s*\(/.test(viteContent)) {
7434
7080
  warnings.push("vite.config is missing inventiveUiVite() \u2014 compile-first CSS will not generate");
7435
7081
  hints.push("Wire plugins: [...inventiveUiVite({ root: import.meta.dirname }), react()]");
@@ -7443,11 +7089,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7443
7089
  "webpack.config.mjs",
7444
7090
  "webpack.config.ts"
7445
7091
  ];
7446
- const webpackPath = webpackCandidates.map((name) => path24.join(cwd, name)).find((p) => fs19.existsSync(p));
7092
+ const webpackPath = webpackCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
7447
7093
  if (!webpackPath) {
7448
7094
  warnings.push("Webpack tooling detected but no webpack.config.* found");
7449
7095
  } else {
7450
- const webpackContent = fs19.readFileSync(webpackPath, "utf-8");
7096
+ const webpackContent = fs18.readFileSync(webpackPath, "utf-8");
7451
7097
  if (!/inventiveUiWebpack\s*\(/.test(webpackContent)) {
7452
7098
  warnings.push("webpack.config is missing inventiveUiWebpack() \u2014 compile-first CSS will not generate");
7453
7099
  hints.push('Wire plugins: [...inventiveUiWebpack()] from "@inventive-ui/framework/webpack"');
@@ -7457,11 +7103,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7457
7103
  }
7458
7104
  if (projectHasNextTooling(cwd)) {
7459
7105
  const nextCandidates = ["next.config.ts", "next.config.mjs", "next.config.js", "next.config.cjs"];
7460
- const nextPath = nextCandidates.map((name) => path24.join(cwd, name)).find((p) => fs19.existsSync(p));
7106
+ const nextPath = nextCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
7461
7107
  if (!nextPath) {
7462
7108
  warnings.push("Next.js detected but no next.config.* found");
7463
7109
  } else {
7464
- const nextContent = fs19.readFileSync(nextPath, "utf-8");
7110
+ const nextContent = fs18.readFileSync(nextPath, "utf-8");
7465
7111
  if (!/withIUI\s*\(/.test(nextContent)) {
7466
7112
  warnings.push("next.config is missing withIUI() \u2014 compile-first CSS will not generate");
7467
7113
  hints.push('Wrap config: export default withIUI({ ... }) from "@inventive-ui/framework/next"');
@@ -7474,18 +7120,18 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7474
7120
  "src/app/layout.jsx",
7475
7121
  "app/providers.tsx",
7476
7122
  "src/app/providers.tsx"
7477
- ].map((rel) => path24.join(cwd, rel));
7478
- const readableLayouts = layoutCandidates.filter((file) => fs19.existsSync(file));
7123
+ ].map((rel) => path23.join(cwd, rel));
7124
+ const readableLayouts = layoutCandidates.filter((file) => fs18.existsSync(file));
7479
7125
  const hasRegistry = readableLayouts.some((file) => {
7480
7126
  try {
7481
- return /\bIUIRegistry\b/.test(fs19.readFileSync(file, "utf-8"));
7127
+ return /\bIUIRegistry\b/.test(fs18.readFileSync(file, "utf-8"));
7482
7128
  } catch {
7483
7129
  return false;
7484
7130
  }
7485
7131
  });
7486
7132
  const hasBootstrapImport = readableLayouts.some((file) => {
7487
7133
  try {
7488
- const content = fs19.readFileSync(file, "utf-8");
7134
+ const content = fs18.readFileSync(file, "utf-8");
7489
7135
  return /next\/bootstrap/.test(content) || /["']iui-bootstrap["']/.test(content) || /iui\/bootstrap/.test(content);
7490
7136
  } catch {
7491
7137
  return false;
@@ -7493,7 +7139,7 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7493
7139
  });
7494
7140
  const hasProvider = readableLayouts.some((file) => {
7495
7141
  try {
7496
- return /\bIUIProvider\b/.test(fs19.readFileSync(file, "utf-8"));
7142
+ return /\bIUIProvider\b/.test(fs18.readFileSync(file, "utf-8"));
7497
7143
  } catch {
7498
7144
  return false;
7499
7145
  }
@@ -7524,14 +7170,14 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7524
7170
  "src/app/providers.tsx",
7525
7171
  "app/layout.tsx",
7526
7172
  "src/app/layout.tsx"
7527
- ].map((rel) => path24.join(cwd, rel));
7173
+ ].map((rel) => path23.join(cwd, rel));
7528
7174
  for (const file of entryCandidates) {
7529
- if (!fs19.existsSync(file)) continue;
7175
+ if (!fs18.existsSync(file)) continue;
7530
7176
  try {
7531
- const content = fs19.readFileSync(file, "utf-8");
7177
+ const content = fs18.readFileSync(file, "utf-8");
7532
7178
  if (/from\s+['"][^'"]*\.generated['"]/.test(content) || /import\s+['"][^'"]*\.generated['"]/.test(content)) {
7533
7179
  warnings.push(
7534
- `Do not import .generated style-map files into the browser (${path24.relative(cwd, file)})`
7180
+ `Do not import .generated style-map files into the browser (${path23.relative(cwd, file)})`
7535
7181
  );
7536
7182
  hints.push(
7537
7183
  "Keep style maps on the scanner path (default src + .iui/generated, or override build.scanDirs) \u2014 see Framework compile-first docs"
@@ -7551,9 +7197,9 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7551
7197
  hints.push(
7552
7198
  "Compile-first: avoid dynamic utility templates like `p-${n}` \u2014 use static strings, style maps, or safelist (ESLint: customPlugin/no-dynamic-utility-class)"
7553
7199
  );
7554
- const giPath = path24.join(cwd, ".gitignore");
7555
- if (fs19.existsSync(giPath)) {
7556
- const gi = fs19.readFileSync(giPath, "utf-8");
7200
+ const giPath = path23.join(cwd, ".gitignore");
7201
+ if (fs18.existsSync(giPath)) {
7202
+ const gi = fs18.readFileSync(giPath, "utf-8");
7557
7203
  if (!gi.includes(".iui/cache/")) {
7558
7204
  warnings.push(".gitignore missing IUI cache directory (.iui/cache/)");
7559
7205
  hints.push("Run iui init or append .iui/cache/ from the IUI docs");
@@ -7564,11 +7210,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7564
7210
  function checkMetadataPortability(cwd = process.cwd()) {
7565
7211
  const warnings = [];
7566
7212
  const hints = [];
7567
- const iuiPath = path24.join(cwd, IUI_DIR);
7568
- const projectPath = path24.join(iuiPath, "project.json");
7569
- if (fs19.existsSync(projectPath)) {
7213
+ const iuiPath = path23.join(cwd, IUI_DIR);
7214
+ const projectPath = path23.join(iuiPath, "project.json");
7215
+ if (fs18.existsSync(projectPath)) {
7570
7216
  try {
7571
- const meta = fs19.readJsonSync(projectPath);
7217
+ const meta = fs18.readJsonSync(projectPath);
7572
7218
  const repoUrl = meta.repoUrl ?? "";
7573
7219
  if (/^[A-Za-z]:[\\/]/.test(repoUrl) || repoUrl.startsWith("/") && !repoUrl.startsWith("//") || repoUrl.startsWith("file:")) {
7574
7220
  warnings.push("project.json repoUrl is a local filesystem path \u2014 use a git remote URL");
@@ -7577,15 +7223,15 @@ function checkMetadataPortability(cwd = process.cwd()) {
7577
7223
  } catch {
7578
7224
  }
7579
7225
  }
7580
- const workspacePath = path24.join(iuiPath, "workspace.json");
7581
- if (fs19.existsSync(workspacePath)) {
7226
+ const workspacePath = path23.join(iuiPath, "workspace.json");
7227
+ if (fs18.existsSync(workspacePath)) {
7582
7228
  try {
7583
- const ws = fs19.readJsonSync(workspacePath);
7229
+ const ws = fs18.readJsonSync(workspacePath);
7584
7230
  if (ws.iuiRoot) {
7585
7231
  warnings.push("workspace.json contains deprecated iuiRoot \u2014 remove it (root is implicit)");
7586
7232
  }
7587
7233
  for (const pkg of ws.packages ?? []) {
7588
- if (/^[A-Za-z]:[\\/]/.test(pkg) || path24.isAbsolute(pkg)) {
7234
+ if (/^[A-Za-z]:[\\/]/.test(pkg) || path23.isAbsolute(pkg)) {
7589
7235
  warnings.push(`workspace.json packages entry is absolute: ${pkg}`);
7590
7236
  hints.push("packages should be relative paths from the IUI root");
7591
7237
  }
@@ -7594,9 +7240,9 @@ function checkMetadataPortability(cwd = process.cwd()) {
7594
7240
  }
7595
7241
  }
7596
7242
  const scanCachePath = iuiCacheFile(cwd, "scan");
7597
- if (fs19.existsSync(scanCachePath)) {
7243
+ if (fs18.existsSync(scanCachePath)) {
7598
7244
  try {
7599
- const cache = fs19.readJsonSync(scanCachePath);
7245
+ const cache = fs18.readJsonSync(scanCachePath);
7600
7246
  const absoluteKeys = Object.keys(cache.files ?? {}).filter(
7601
7247
  (key) => /^[A-Za-z]:[\\/]/.test(key) || key.startsWith("/") && !key.startsWith("//")
7602
7248
  );
@@ -7613,38 +7259,70 @@ function checkMetadataPortability(cwd = process.cwd()) {
7613
7259
  }
7614
7260
  return { warnings, hints };
7615
7261
  }
7616
- function checkAssetBoundBindings(cwd = process.cwd()) {
7617
- const assetsPath = path24.join(cwd, ASSETS_CONFIG_FILE);
7618
- if (!fs19.existsSync(assetsPath)) {
7619
- return { ok: true, summary: "Asset binding check skipped (no assets.config.json)" };
7262
+ var ICON_LIBRARY_PACKAGES = {
7263
+ "material-symbols": "material-symbols",
7264
+ materialSymbols: "material-symbols",
7265
+ "material-icons": "icons-material",
7266
+ lucide: "icons-lucide",
7267
+ phosphor: "icons-phosphor"
7268
+ };
7269
+ function checkAssetPipeline(cwd = process.cwd()) {
7270
+ const assetsPath = path23.join(cwd, ASSETS_CONFIG_FILE);
7271
+ if (!fs18.existsSync(assetsPath)) {
7272
+ return { ok: true, summary: "Asset check skipped (no assets.config.json)" };
7620
7273
  }
7621
7274
  let assets2;
7622
7275
  try {
7623
- assets2 = fs19.readJsonSync(assetsPath);
7276
+ assets2 = fs18.readJsonSync(assetsPath);
7624
7277
  } catch {
7625
7278
  return { ok: false, summary: "assets.config.json is not valid JSON" };
7626
7279
  }
7627
- if (assets2.binding !== "scanned") {
7628
- return { ok: true, summary: "Asset slots use lazy binding (default)" };
7280
+ const packagesDir = path23.join(cwd, "node_modules", "@inventive-ui");
7281
+ const frameworkPkg = path23.join(packagesDir, "framework", "package.json");
7282
+ if (fs18.existsSync(frameworkPkg)) {
7283
+ const framework = fs18.readJsonSync(frameworkPkg);
7284
+ if (!framework.exports?.["./assets"]) {
7285
+ return {
7286
+ ok: false,
7287
+ summary: "Installed @inventive-ui/framework has no asset pipeline",
7288
+ details: "Update it: iui update"
7289
+ };
7290
+ }
7291
+ }
7292
+ const library = assets2.icon?.library;
7293
+ const pkg = library ? ICON_LIBRARY_PACKAGES[library] : void 0;
7294
+ if (!pkg) return { ok: true, summary: "Asset config valid" };
7295
+ const iconsDir = path23.join(packagesDir, pkg, "dist", "icons");
7296
+ if (!fs18.existsSync(iconsDir)) {
7297
+ return {
7298
+ ok: false,
7299
+ summary: `Icon library "${library}" is configured but @inventive-ui/${pkg} is not installed`,
7300
+ details: `Install it: iui install assets @inventive-ui/${pkg}`
7301
+ };
7629
7302
  }
7630
- const registerBound = path24.join(generatedAssetsDir(cwd), "register-bound.ts");
7631
- if (!fs19.existsSync(registerBound)) {
7303
+ const glyphs = [
7304
+ ...Object.entries(assets2.icon?.globalIcons ?? {}).map(([alias, glyph]) => [`@${alias}`, glyph]),
7305
+ ["placeholder", assets2.icon?.placeholder?.name],
7306
+ ["fallback", assets2.icon?.fallback]
7307
+ ].filter((entry) => typeof entry[1] === "string" && entry[1].length > 0);
7308
+ const missing = glyphs.filter(([, glyph]) => !fs18.existsSync(path23.join(iconsDir, `${glyph}.js`)));
7309
+ if (missing.length > 0) {
7632
7310
  return {
7633
7311
  ok: false,
7634
- summary: 'binding is "scanned" but .iui/generated/assets/register-bound.ts is missing',
7635
- details: "Run any iui command to refresh the slot registry, or reinstall asset packages."
7312
+ summary: `${missing.length} icon alias${missing.length === 1 ? "" : "es"} point at glyphs "${library}" does not have`,
7313
+ details: missing.slice(0, 8).map(([name, glyph]) => `${name} \u2192 ${glyph}`).join(", ")
7636
7314
  };
7637
7315
  }
7638
- return { ok: true, summary: "Scanned asset bindings present" };
7316
+ return { ok: true, summary: `Asset config valid (${glyphs.length} icon names checked in ${library})` };
7639
7317
  }
7640
7318
  function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7641
7319
  const iuiRoot2 = resolveIuiProjectRoot(cwd);
7642
7320
  const generatedPath = bootstrapGeneratedPath(iuiRoot2);
7643
- const bridgePath = path24.join(cwd, "src", "iui", "bootstrap.ts");
7644
- if (!fs19.existsSync(generatedPath)) {
7321
+ const bridgePath = path23.join(cwd, "src", "iui", "bootstrap.ts");
7322
+ if (!fs18.existsSync(generatedPath)) {
7645
7323
  if (options.autoFix) {
7646
7324
  writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7647
- if (fs19.existsSync(generatedPath)) {
7325
+ if (fs18.existsSync(generatedPath)) {
7648
7326
  return { ok: true, summary: "Generated bootstrap artifacts repaired" };
7649
7327
  }
7650
7328
  }
@@ -7654,10 +7332,10 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7654
7332
  details: "Expected .iui/generated/bootstrap.generated.tsx \u2014 run iui doctor --fix."
7655
7333
  };
7656
7334
  }
7657
- if (!fs19.existsSync(bridgePath)) {
7335
+ if (!fs18.existsSync(bridgePath)) {
7658
7336
  if (options.autoFix) {
7659
7337
  writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7660
- if (fs19.existsSync(bridgePath)) {
7338
+ if (fs18.existsSync(bridgePath)) {
7661
7339
  return { ok: true, summary: "Bootstrap bridge repaired" };
7662
7340
  }
7663
7341
  }
@@ -7670,8 +7348,8 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7670
7348
  const configs = resolveProjectConfigPaths(iuiRoot2);
7671
7349
  const missing = [];
7672
7350
  for (const [key, rel] of Object.entries(configs)) {
7673
- const abs = path24.resolve(iuiRoot2, rel.replace(/^\.\//, ""));
7674
- if (!fs19.existsSync(abs)) missing.push(`${key}: ${rel}`);
7351
+ const abs = path23.resolve(iuiRoot2, rel.replace(/^\.\//, ""));
7352
+ if (!fs18.existsSync(abs)) missing.push(`${key}: ${rel}`);
7675
7353
  }
7676
7354
  if (missing.length > 0) {
7677
7355
  return {
@@ -7681,7 +7359,7 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7681
7359
  };
7682
7360
  }
7683
7361
  const expected = expectedBootstrapImportPaths(iuiRoot2);
7684
- const generated = fs19.readFileSync(generatedPath, "utf8");
7362
+ const generated = fs18.readFileSync(generatedPath, "utf8");
7685
7363
  const stale = [];
7686
7364
  for (const [key, importPath] of Object.entries(expected)) {
7687
7365
  if (!generated.includes(`"${importPath}"`)) {
@@ -7691,7 +7369,7 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7691
7369
  if (stale.length > 0) {
7692
7370
  if (options.autoFix) {
7693
7371
  writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7694
- const refreshed = fs19.readFileSync(bootstrapGeneratedPath(iuiRoot2), "utf8");
7372
+ const refreshed = fs18.readFileSync(bootstrapGeneratedPath(iuiRoot2), "utf8");
7695
7373
  const stillStale = Object.entries(expected).filter(
7696
7374
  ([, importPath]) => !refreshed.includes(`"${importPath}"`)
7697
7375
  );
@@ -7817,12 +7495,12 @@ async function runConfigTierDiagnostics(targetCwd, opts, counters, options = {})
7817
7495
  hint(hint2);
7818
7496
  }
7819
7497
  }
7820
- const assetBound = checkAssetBoundBindings(targetCwd);
7821
- if (assetBound.ok) {
7822
- pass(assetBound.summary);
7498
+ const assetPipeline = checkAssetPipeline(targetCwd);
7499
+ if (assetPipeline.ok) {
7500
+ pass(assetPipeline.summary);
7823
7501
  } else {
7824
- warn(assetBound.summary);
7825
- if (assetBound.details) hint(assetBound.details);
7502
+ warn(assetPipeline.summary);
7503
+ if (assetPipeline.details) hint(assetPipeline.details);
7826
7504
  }
7827
7505
  }
7828
7506
  async function runPackageDiagnostics(targetCwd, opts, counters) {
@@ -7978,7 +7656,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7978
7656
  async function doctorCommand(opts) {
7979
7657
  try {
7980
7658
  const invocationCwd = process.cwd();
7981
- const targets = opts?.cwd ? [path25.resolve(opts.cwd)] : resolveSetupDoctorTargets(invocationCwd);
7659
+ const targets = opts?.cwd ? [path24.resolve(opts.cwd)] : resolveSetupDoctorTargets(invocationCwd);
7982
7660
  const installRoot = resolveDependencyInstallRoot(invocationCwd);
7983
7661
  const multiPackage = targets.length > 1;
7984
7662
  heading("Diagnostics");
@@ -8021,7 +7699,7 @@ async function doctorCommand(opts) {
8021
7699
  for (const targetCwd of targets) {
8022
7700
  if (multiPackage) {
8023
7701
  newline();
8024
- const label = path25.relative(installRoot, targetCwd) || path25.basename(targetCwd);
7702
+ const label = path24.relative(installRoot, targetCwd) || path24.basename(targetCwd);
8025
7703
  kv("Package", label);
8026
7704
  }
8027
7705
  await runPackageDiagnostics(targetCwd, opts, counters);
@@ -8049,9 +7727,9 @@ async function doctorCommand(opts) {
8049
7727
 
8050
7728
  // src/commands/setup.ts
8051
7729
  function detectDevScript(cwd) {
8052
- const pkgPath = path26.join(cwd, "package.json");
7730
+ const pkgPath = path25.join(cwd, "package.json");
8053
7731
  try {
8054
- const pkg = fs20.readJsonSync(pkgPath);
7732
+ const pkg = fs19.readJsonSync(pkgPath);
8055
7733
  if (pkg.scripts?.dev) return "npm run dev";
8056
7734
  if (pkg.scripts?.start) return "npm run start";
8057
7735
  } catch {
@@ -8060,8 +7738,8 @@ function detectDevScript(cwd) {
8060
7738
  return null;
8061
7739
  }
8062
7740
  function relativePackageLabel(installRoot, packageDir) {
8063
- const rel = path26.relative(installRoot, packageDir);
8064
- return rel && rel !== "." ? rel : path26.basename(packageDir);
7741
+ const rel = path25.relative(installRoot, packageDir);
7742
+ return rel && rel !== "." ? rel : path25.basename(packageDir);
8065
7743
  }
8066
7744
  async function setupCommand(opts) {
8067
7745
  try {
@@ -8070,7 +7748,7 @@ async function setupCommand(opts) {
8070
7748
  const installRoot = resolveDependencyInstallRoot(cwd);
8071
7749
  const workspaceRoot = findWorkspaceRoot(cwd);
8072
7750
  const inMonorepo = workspaceRoot !== null;
8073
- const installFromChild = inMonorepo && path26.resolve(installRoot) !== path26.resolve(cwd);
7751
+ const installFromChild = inMonorepo && path25.resolve(installRoot) !== path25.resolve(cwd);
8074
7752
  if (!hasPackageJson(cwd) && !hasPackageJson(installRoot)) {
8075
7753
  throw new CLIError(
8076
7754
  "No package.json found in the current directory.",
@@ -8104,7 +7782,7 @@ async function setupCommand(opts) {
8104
7782
  for (const w of warnings) warn(w);
8105
7783
  kv("Package manager", `${pm} (${source})`);
8106
7784
  if (installFromChild) {
8107
- const rel = path26.relative(cwd, installRoot) || ".";
7785
+ const rel = path25.relative(cwd, installRoot) || ".";
8108
7786
  kv("Install directory", rel === ".." || rel.includes("..") ? installRoot : rel);
8109
7787
  }
8110
7788
  const installCmd2 = syncInstallCommand(pm);
@@ -8118,7 +7796,7 @@ async function setupCommand(opts) {
8118
7796
  } catch (err) {
8119
7797
  installSpinner.fail("Dependency install failed");
8120
7798
  const detail = formatExecSyncError(err);
8121
- const manual = path26.resolve(installRoot) === path26.resolve(cwd) ? installCmd2 : `cd ${JSON.stringify(installRoot)} && ${installCmd2}`;
7799
+ const manual = path25.resolve(installRoot) === path25.resolve(cwd) ? installCmd2 : `cd ${JSON.stringify(installRoot)} && ${installCmd2}`;
8122
7800
  throw new CLIError(
8123
7801
  detail ? `Could not install project dependencies.
8124
7802
  ${detail}` : "Could not install project dependencies.",
@@ -8276,7 +7954,7 @@ async function updateCommand(opts = {}) {
8276
7954
  const auth = await ensureAuthSession();
8277
7955
  await ensureLicenseSession();
8278
7956
  const inProject = isInsideProject();
8279
- const currentCliVersion = true ? "0.0.10" : "unknown";
7957
+ const currentCliVersion = true ? "0.0.11" : "unknown";
8280
7958
  const latestCliVersion = await fetchLatestCliVersion(auth.token);
8281
7959
  const cliUpdateAvailable = latestCliVersion !== null && isVersionGreater(latestCliVersion, currentCliVersion);
8282
7960
  if (latestCliVersion && cliUpdateAvailable) {
@@ -8558,7 +8236,7 @@ var AUTH_EXEMPT_COMMANDS = /* @__PURE__ */ new Set([
8558
8236
  "doctor",
8559
8237
  "list"
8560
8238
  ]);
8561
- program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.10" : "1.0.0").option("-C, --cwd <dir>", "Run as if started in the given directory").option("-q, --quiet", "Minimal output (also respects IUI_QUIET=1)").option("--no-color", "Disable ANSI colors");
8239
+ program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.11" : "1.0.0").option("-C, --cwd <dir>", "Run as if started in the given directory").option("-q, --quiet", "Minimal output (also respects IUI_QUIET=1)").option("--no-color", "Disable ANSI colors");
8562
8240
  program.command("login").description("Authenticate with GitHub and link your license").option("-f, --force", "Force re-authentication and register this device").option("--bootstrap", "After login, run optional setup prompts").action((opts) => loginCommand(opts));
8563
8241
  program.command("logout").description("Remove stored credentials").action(logoutCommand);
8564
8242
  program.command("whoami").description("Show authenticated identity and license details").action(whoamiCommand);
@@ -8641,7 +8319,7 @@ program.command("update").description("Check for and apply framework, component,
8641
8319
  var assets = program.command("assets").description("Manage asset packages (icons, illustrations, logos, etc.)");
8642
8320
  assets.command("remove <package>").description("Remove an installed asset package").action((pkg) => assetsRemoveCommand(pkg));
8643
8321
  assets.command("list").description("Show all available and installed asset packages").action(assetsListCommand);
8644
- program.command("doctor").description("Run project health diagnostics (read-only by default)").option("--fix", "Apply safe config patches (iui.config, vite.config, component.config)").option("--config-only", "Validate project config tiers only (no auth/registry)").action((opts) => doctorCommand(opts));
8322
+ program.command("doctor").description("Run project health diagnostics (read-only by default)").option("--fix", "Apply safe config patches (theme.config, vite.config, component.config)").option("--config-only", "Validate project config tiers only (no auth/registry)").action((opts) => doctorCommand(opts));
8645
8323
  if (shouldShowBanner()) {
8646
8324
  printBanner();
8647
8325
  }
@@ -8656,7 +8334,7 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
8656
8334
  const root = topLevelCommandName(actionCommand);
8657
8335
  const globalOpts = program.opts();
8658
8336
  if (globalOpts.cwd) {
8659
- process.chdir(path27.resolve(globalOpts.cwd));
8337
+ process.chdir(path26.resolve(globalOpts.cwd));
8660
8338
  }
8661
8339
  if (isInsideProject()) {
8662
8340
  try {